Map 과 Set

** 이 포스트 에서는 Map 과 Set 에 대해 알아보도록 하겠습니다 **

Map (Java Platform SE 8 )
Set (Java Platform SE 8 )

# 핵심

  • Map은 Key, Value 쌍을 가지는 오브젝트 입니다. Key는 중복될 수 없습니다.
  • Set은 수학 에서의 집합과 동일한 개념 입니다. 중복되지 않는 값을 갖는 오브젝트 입니다.
  • Map과 Set 모두 순서를 보장하지 않습니다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void mapKeyTest() {
final Map<Integer, String> player = new HashMap<>();
player.put(1, "Djokovic");
player.put(2, "Murray");
player.put(1, "Murray");
assertEquals(2, player.size());
assertEquals("Murray", player.get(1));
assertEquals("Murray", player.get(2));
}

@Test
public void setValueTest() {
final Set<String> player = new HashSet<>();
player.add("Djokovic");
player.add("Nadal");
player.add("Federer");
player.add("Murray");
player.add("Djokovic");
assertEquals(4, player.size());
}

key는 Integer, value는 String인 HashMap의 play라는 변수를 만들고
1 에 조코비치, 2 에 머레이를 넣었습니다.
다시 1에 머레이를 넣게되면 나중에 들어간 머레이가 조코비치를 덮어써버려서 결국 key 1, 2의 value는 모두 “Murray”가 된것을 확인할 수 있습니다.

Set에는 값만 들어있기 때문에 4명의 플레이어의 이름을 넣고, 다섯번째에 “Djokovic”을 한번 더 넣었음에도 불구하고
중복값은 허용되지 않기 때문에 player set의 size는 여전히 4인것을 알 수 있습니다.

위의 예에서 사용한 HashMap은 Java에서 Map Interface를 사용하는 가장 일반적인 방식 입니다.

ArrayList 와 LinkedList +@ 에서도 잠깐 언급한 적이 있는데 멀티 쓰레드로 개발을 하는 경우는 항상 사용하고자 하는 클래스나 인터페이스가 **Thread safe** 한지 살펴 봐야 합니다.

HashMap은 동기화 되어있지 않기 때문에 동시에 여러개의 쓰레드가 동시에 값을 수정할 경우 익셉션이 발생할 수 있으니 필요한 경우 Collections.synchronizedMap 함수를 사용하거나 ConcurrentHashMap을 사용하여 이 문제를 회피할 수 있습니다.
(JDK1.5 부터 등장한 ConcurrentHashMap을 사용하는 편이 더 효율적 입니다.)

# HashMap에서 Hash는 무슨 역할을 하는가

네이버의 helloworld 블로그에 자세한 동작방식이 설명되어 있으니 궁금하신분들은 한번씩 읽어보시면 도움이 될것 같습니다.

요약해서 쉽게 설명을 해 보면

HashMap은 key-value 페어를 담을수 있는 buckets을 가지고 있습니다.
put(key,value)메소드를 호출하면 각 key-value 페어가 어느 bucket에 들어갈지 결정할때 바로 hashCode()함수가 사용 됩니다.

get(key)를 호출한 경우에도 어느 bucket에서 데이터를 가져올지 결정할때 hashCode()가 사용 됩니다.
(내부적으로 이 hashcode의 리턴값으로 shift 연산을 통해 결정된다고 하네요)

어느 bucket인지 알았으면 실제 그버킷에 들어있는 모든 키의 hashcode 값끼리 equals()를 통해 원하는 put이나 get 의 결과를 얻을 수 있게 됩니다.

# +@ HashMap VS HashTable

  1. Hashtable은 synchronized, HashMap 은 아님
  2. Hashtable 은 null을 key나 value로 가질수 없음, Hashmap은 하나의 null key와 여러개의 null 값을 가질 수 있음
  3. Hashmap을 사용하다가 순서가 중요해 진 경우 단순히 Hashmap의 선언부를 LinkedHashMap으로 변경해주면 나머지 코드는 건드릴 필요가 없으나 Hashtable로 하려면 골치가 아파짐.
Share