본문 바로가기
java

collections framework - HashMap

by proudev 2023. 9. 3.

HashMap과 Hashtable - 순서X, 중복(키X,값O)

- Map 인터페이스를 구현. 데이터를 키와 값의 쌍으로 저장

key : 중복 X

value : 중복 가능 

즉, id는 중복은 안되나 비밀번호는 중복 가능하다.

  Map  
Hashtable HashMap SortedMap
  LinkedHashMap TreeMap

Hashtable : 동기화 O

HashMap  : 동기화 X

TreeMap : TreeSet과 같은 특징을 가지고 있다(이진 탐색 트리)

LinkedHashMap: Map은 순서를 유지하고 있지 않으나 순서를 유지하고 싶으면!!

 

HashMap

- Map 인터페이스를 구현한 대표적인 컬렉션 클래스

- 순서를 유지하려면, LinkedHashMap 클래스를 사용하면 된다.

 

TreeMap

- 범위 검색과 정렬에 유리한 컬렉션 클래스

- HashMap보다 데이터 추가, 삭제에 시간이 더 걸림(비교해가면서 저장하기 때문)

- TreeSet과 유사함 왜냐하면 같은 Tree구조이기 때문임.


HashMap의 키(key)와 값(value)

- 해싱(hashing)기법으로 데이터를 저장, 데이터가 많아도 검색이 빠르다.

- Map 인터페이스를 구현. 데이터를 키와 값의 쌍으로 저장

키(key) 컬렉션 내의 키(key) 중에서 유일해야 한다.
값(value) 키(key)와 달리 데이터 중복을 허용한다.

HashMap map= new HashMap();
map.put("abc", "123");
map.put("abdcd", "123");
map.put("abdcd", "11");

(중요) map의 요소를 저장 중 key가 똑같으면 맨 마지막 value로 덮어쓴다.

 


해싱(hashing) - 1

해싱은 해시함수를 이용해서 저장하고 읽어오는 것

어떤 key 값을 넣으면 배열의 index를 알려줌(저장 위치를 알려줌)

이것을 해쉬코드(hashcode)라고함.

해쉬코드는 저장위치임.

해싱은 해쉬함수를 이용해서 데이터를 저장하고 읽고하는 것

저장하고 읽고 올때 저장위치가 같아야 한다.(같은 키를 넣으면 같은 해쉬코드 나와야함)

 

해싱(hashing) - 2

해시함수(hash function)로 해시테이블(hash table)에 데이터를 저장, 검색

(중요) 해시함수는 key를 넣으면 저장위치(hashcode)준다. 저장위치는 hashcode 배열의 인덱스이다.

(중요!!) 해시테이블배열과 링크드 리스트(LinkedList)가 조합된 형태

해시테이블은 데이터들은 저장하는 공간을 해시테이블(저장된 방식이 2차원 배열(테이블처럼)과 같이 생김)

 

LinkedList처럼 한 이유는 변경하기 쉽게 하기 위해!!

배열은 인덱스만 알면 한번에 찾아갈 수 있음(접근성 GOOD)

그래서 배열의 장점인 접근성LinkedList의 변경하기 유리한 장점을 합친 것이 Hashtable이다.

즉, LinkedList를 배열처럼 묶어 2차원 배열처럼 만든거다.

 

해싱 함수 :

Objects.hash()

해싱을 사용하는 클래스

Hashtable;
HashMap;
HashSet;

 

해싱테이블에 저장된 데이터를 가져오는 과정

해시코드는 배열의 인덱스

1. 키로 해시함수를 호출해서 해시코드를 얻는다,

2. 해시코드(해시함수의 반환값)에 대응하는 링크드 리스트를 배열에서 찾는다.

3. 링크드 리스트에서 키와 일치하는 데이터를 찾는다

* 해시함수는 같은 키에 대해 항상 같은 해시코드를 반환해야한다.

* 서로 다른 키일지라도 같은 값의 해시코드를 반환할 수 있다.

 


HashMap - 주요 메서드

 

생성자

생성자는 해시테이블에 저장(해시 테이블 = 배열 + 링크드 리스)

HashMap( ) 기본 생성자
HashMap(int initialCapacity) 배열 초기용량
HashMap(int initialCapacity, float loadFactor) 배열 초기용량, 생성자를 더 늘이는 기준 퍼센트(예: 0.8)
HashMap(Map m) Map m 객체를 전부 HashMap에 저장

 

데이터 관리

Object put(Object key, Object value) 매개변수에 해당하는 key, value 저장
void putAll(Map m) Map m 객체 저장
Object remove(Object key) 삭제
Object replace(Object key, Object value) 변경(기존의 key의 value값을 새로 지정함)
boolean replace(Object key, Object oldValue, Object newValue) 변경

 

기타 메서드

Set entrySet() key와 value값 쌍으로 Set으로 만듬
Set KeySet() key값만 Set으로 만
Collection values() value만 가져온다.
Object get(Object key) key를 매개변수에 넣으면 해당 value 반환
Object getOrDefault(Object key, Object defaultValue) key가 없으면 defaultValue값을 반환
boolean containsKey(Object key) 지정된 key가 있는지
boolean containsValue(Object value) 지정된 value가 있는지
int size() 실제 값이 들어 있는 사이즈 정수 값 반환
boolean isEmpty() 비어 있는지 확인
void clear() 모두 삭제
Object clone 복제하는 것

 

 

아래와 같이 동일한 key의 value를 추가할 수 있다(에러는 발생하지 않는다)

대신 기존의 value를 값을 새로운 value값으로 덮어쓰기가 된다.

public static void main(String[] args){
   HashMap map = new HashMap();
   map.put("myId", "1234");
   map.put("myId2", "1111");
   System.out.println(map); [myId=1234, myId2=1111];
   map.put("myId2", "1234");
   System.out.println(map); [myId=1234, myId2=1234];
}

 

예제

HashMap map = new HashMap();

map.put("김자바", new Integer(90));
map.put("김자바", new Integer(100)); key가 같기에 value 값을 덮어씀
map.put("이자바", new Integer(40));
map.put("아자바", new Integer(50));
map.put("나자바", new Integer(70));

Set set = map.entrySet();  key,value를 한 쌍으로 Set에 저장함
Iterator it = set.iterator();

while(it.hasNext()){
   Map.Entry e = (Map.Entry)it.next(); key,value로 저장된 Set의 요소를 Map로 바꿈
   System.out.println("이름: " + e.getKey()+" , 점수: "+ e.getValue());
} 
// Map 인터페이스, Entry 인터페이스(Map의 내부인터페이스)이다. 
// 즉, Map 인터페이스 안에 또 다른 Entry라는 인터페이스가 있는 것이다.

set = map.keySet(); // map의 key요소만 받아서 set 참조변수에 저장
System.out.println("참가자 명단 : "+ set);

Collection values = map.values();   map에 value값들만 뽑아서 Collection에 저장함
it = values.iterator();

int total = 0;

while(it.hasNext()){
   int i = (int)it.next();
   total += i;
}

System.out.println("총점: " + total);
System.out.println("평균: " + (float)total/set.size());
System.out.println("최고점수: " + Collections.max(values));    
System.out.println("최저점수: " + Collections.min(values));

Collection.max(), Collection.min() 매서드에는 Comparable를 구현한 클래스만 들어올 수 있다.
왜냐하면 비교 기준이 있어야하기 때문이다.

 

예제

public static void main(String[] args){
   String[] data = {"A", "K" ,"A" ,"K", "D", "Z"};
   
   HashMap map = new HashMap();
   
   for(int i=0;i<data.length;i++){
      if(map.contain(data[i]){
      	 int value = map.getValue(data[i]);
         map.put(data[i], value + 1);
      }else {
         map.put(data[i], 1);
      }
   }
   
   Iterator it = map.entrySet().iterator();
   
   while(it.hasNext()){
      Map.Entry entry = (Map.Entry)it.next();
      int value = (int)entry.getValue();
      System.out.println(entry.getKey() + " : " + printBar('#', value) + " " + value);
   }
}

댓글