- 맵은 해시라고도 하며 배열이나 사전(dictionary)과 관련 잇는 키-값 형태의 저장소.
- 맵을 구현할 때는 Map 인터페이스를 사용한다.
- List 인터페이솨 달리 Collection 인터페이스를 구현하지 않는다는 차이가 있다,
- 맵의 특징 중 하나는 키 값은 트리 상에서 한 번만 나타난다는 것.
맵에서 키를 덮어 쓰는 예
- HashMap 클래스는 해시 테이블을 자바로 구현한 것으로, 클래스 구현에는 키-값 쌍을 나타내는 Entry라는 내부 클래스가 있다.
- 원소들은 Entry 객체의 배열로 저장할 수도 있고 배열 대신 Entry 객체의 리스트로 저장할 수도 있다.
- 이렇게 저장된 원소의 특정 키 인스턴스의 값은 테이블의 어디에 해당 값이 있는지 정의
- Object 클래스에 정의된 HashCode 메서드는 int 타입 값을 반환하며 이 값은 테이블 어디에 키-값 쌍이 있는지 확인하는데 사용
- hashCode 메서드는 두 개의 같은 인스턴스는 같은 hashCode메서드 값을 반환해야 한다.
- 하지만 반대는 성립하지 않는다. 두 개의 hashCode 값이 같은 인스턴스를 가리키지 않는다.
- HashMap 클래스용으로 테이블에 값을 삽입했을 때는 hashCode 메서드가 해당 값을 읽은 다음 int 범위 안에 유요한 값이라면 반환되는 값이 될수 있다.
- 반환 값은 보통 테이블 크기보다 작은 0과 1 사이의 값으로 반영됨.
- 동일하지 않은 객체들이 같은 hashCode 메서드 값을 반환할 수도 있는 상황도 고려해야 함.
- 구조상 서로 다른 객체가 같은 해시 테이블에 들어가는 상황이 발생할 수 있기 때문이다. 따라서 충돌이 발생할 경우 처리 방법도 고려 해야 함.
해결 방법
(1) 두 번째 해시 함수를 갖는 것.
- 두 번째 해시 함수는 값을 삽입하려고 할 때 테이블의 위치에 이미 다른 값이 있으면 오프셋 방식으로 해당 값이 삽입될 위치를 다시 계산 함.
- 하지만 이는 단지 충돌을 미룰 뿐 객체의 충돌은 여전히 발생한다.
(2) 각 테이블 원소에 대한 값들의 리스트를 저장하고 같은 테이블 인덱스와 연결되는 모든 테이블 키를 리스트의 값으로 추가 하는것.
- 테이블을 간단하게 순회함으로써 키 복구를 수행하며 맞는 값을 찾을 때 까지 각원소들이 같인지 확인하는 장점이 있다,
- 많은 원소를 가진 작은 테이블이 적은 원소를 가진 큰 테이블보다 충돌이 발생할 가능성이 높다.
- 새로운 HashMap 객체를 생성할 때 백분율을 나타내는 0 과 1 사이의 값으로 부하계수를 명시할 수 있다.
- 테이블은 이 부하계수를 다 채우게 되면 테이블 크기를 2배로 늘린다.
- 테이블 크기가 조정되면 테이블의 모든 원소를 재배치 한다.
- hashCode 메서드 값이 테이블의 인덱스에 맞게 재할당 되기 때문.
- 많은 원소가 있는 테이블의 재할당느 많은 자원과 시간을 소모하는 작업이다.
- 맵에서 많은 원소를 사용할 것이라고 미리 파악했다면 처음 맵을 만들 때 테이블 크기를 재할당 하지 않도록 적당한 크기로 테이블을 초기화 하는것이 좋다.
TreeMap
- TreeMap 클래스는 Map 인터페이스를 구현하느데 이진 트리 자료구조를 이용한다.
- TreeMap 에서 Comparable과 Comparator 인터페이스를 사용한다.
- TreeMap 클래스는 키를 정렬 가능한 순서에 따라 저장하기 때문에 hashCode 메서드는 전혀 사용되지 않는다.
- TreeMap 클래스에 포함된 각종 원소는 균형을 맞춘 트리 구조로 구성되어 있으므로 검색, 삭제, 삽입 같은 모든 동작이 항상 O(log n) 처리 성능을 발휘한다.
- TreeMap과 HashMap의 주된 차이는 순서가 보존되고 보존되지 않는 차이이다.
LinkedHashMap
- 기본적으로 HashMap 클래스와 같은 방식으로 작동한다.
- 그래서 원소를 찾는데 O(1) 성능을 발휘
- 키를 반속 순회할 때 삽입하는 경우와 순서가 같아야 한다.
ConrurentHahMap
- 맵 인스턴스를 많은 스레드에서 공유하고자 한다면 이 방법이 유용
- 스레드 세이프 하고, 맵에 값을 쓰는 도중이라도 값을 읽어서 반환할 수 있다.
'java' 카테고리의 다른 글
몇 가지 자바 원시 타입의 이름을 지정하고 이 타입이 JVM에서 어떻게 처리되는지 설명 (0) | 2017.11.15 |
---|---|
빌더 패턴은 얼마나 유용한가? (0) | 2017.11.15 |
이진 탐색 트리 (0) | 2017.11.15 |
Deque(Double-ended Queue) (0) | 2017.11.15 |
연결큐 (0) | 2017.11.15 |