Map 컬렉션의 구조는 "키와 값 쌍으로 구성된 Map.Entry객체"를 저장하는 구조다.
Map 컬렉션에 저장된 객체 정보는 다음을 통해 Set 컬렉션으로 얻어낼 수 있다.
위에서 얻은 Set 컬렉션에서 값을 하나씩 얻으려면 Iterator를 만들면 된다.
Set<K> keySet = map.keySet();
Iterator<K> iter = keySet.iterator();
while(iter.hasNext()){
K key = iter.next();
V val = map.get(key);
}
Set<Map.Entry<K, V>> entrySet = map.entrySet();
Iterator<Map.Entry<K, V>> iter = entrySet.iterator();
while(iter.hasNext()){
Map.Entry<K, V> entry = iter.next();
K key = entry.getKey();
V val = entry.getValue();
}
Map 컬렉션의 대표적인 자료구조 두가지의 특징을 보자!
HashMap과 HashTable은 동일한 내부구조를 가지고 있다.
다음과 같이 키와 값 쌍을 저장하는 구조다.
Map<K, V> map = new Hashtable<K, V>();
Map<K, V> map = new HashMap<K, V>();
HashMap과 달리, Hashtable은 synchronized 메서드로 구성되어 있다. 즉 Hashtable의 메서드는 멀티스레드로 동시에 돌릴 수 없다. 하나의 스레드가 메서드 실행을 끝내야 다음 것을 돌릴 수 있다.
즉, Hashtable은 thread safe 하다.
Map 컬렉션의 키는 서로 다른 인스턴스이다. 일반적으로 자바 객체를 생성하면, toString()값이 동일하더라도 서로 다른 인스턴스이지 않은가? 그러나 우리는 문자열이 같은 경우 동등한 객체로 다루고 싶은 경우가 많을 것이다.
이렇게 동등객체가 될 조건을 지정하고 싶다면, hashCode()와 equal() 메서드를 재정의해야 한다.
필드값이 같으면 동등객체라고 판단하기 하기 위해서 equals()를 재정의하고, 객체의 해시코드가 아닌 해당 필드의 해시코드를 리턴하도록 재정의할 수 있다.
참고) 키 타입으로 String을 사용할 경우
String 객체는 이미 문자열이 같을 경우 동등객체가 되도록 hashCode()와 equals() 메서드가 재정의되어있는 객체이다. 따라서 문자열이 동일하면, Map 컬렉션에서 동일한 객체로 다룬다.
Node라는 클래스를 내가 정의했다. Node 객체에 대하여 문자열 기준으로 동등하다는 판단을 하기 위해, 다음과 같이 equals()와 hashCode()를 재정의할 수 있다.
class Node{
int x;
int y;
String name;
...
// 필드 값이 일치하면 동일하다고 할 거야
boolean equals(Object obj){
if(obj instanceof Node){
Node node = (Node) obj;
return (x == node.x) && (y == node.y) && (name.equals(node.name));
} else {
return false;
}
}
// 객체의 해시코드가 아니라, 필드의 해시코드를 리턴시킬 거야
int hashCode(){
return Objects.hash(x, y, name);
}
}