본문 바로가기
Java/컬렉션 프레임워크(Collection Framework)

5. Map <K, V>

by mozzi329 2022. 7. 14.
728x90

 

 

키(Key)와 밸류(Value)를 가지는 목욕탕 락커

 

📌 Map <K, V>

Map 인터페이스는 키(key)와 값(value)으로 구성된 객체를 저장하는 구조를 가지고 있다.

여기서 이 객체를 Entry객체라고 하는데, 이 Entry 객체는 키와 값을 각각 Key 객체와 Value 객체로 저장한다.

 

Map의 구조

Map을 사용할 때에 중요한 사실은 키는 중복 저장될 수 없지만, 값은 중복 저장이 가능하다는 것이다. 이는 키의 역할이 값을 식별하는 것이기 때문이다. Map 인터페이스를 구현한 클래스에는 HashMap, Hashtable, TreeMap, SortedMap 등이 있다.

 

✔️ Map의 메서드

기능 리턴 타입 메서드 설명
객체 추가 Object put(Object key, Object value) 주어진 키로 값을 저장
해당 키가 새로운 키일 경우 null을 리턴하지만, 동일한 키가 있을 경우에는 기존의 값을 대체하고 대체되기 이전의 값을 리턴
객체 검색 boolean containsKey(Object key) 주어진 키가 있으면 true, 없으면 false를 리턴
  boolean containsValue(Object value) 주어진 값이 있으면 true, 없으면 false를 리턴
  Set entrySet() 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴
  Object get(Object key) 주어진 키에 해당하는 값을 리턴
  boolean isEmpty() 컬렉션이 비어 있는지 확인
  Set keySet() 모든 키를 Set 객체에 담아서 리턴
  int size() 저장된 Entry 객체의 총 갯수를 리턴
  Collection values() 저장된 모든 값을 Collection에 담아서 리턴
객체 삭제 void clear() 모든 Map.Entry(키와 값)을 삭제
  Object remove(Object key) 주어진 키와 일치하는 Map.Entry를 삭제하고 값을 리턴

 

📌 HashMap

HashMap은 Map 인터페이스를 구현한 대표적인 클래스이다.

 

아래 그림과 같이 키와 값으로 구성된 Entry 객체를 저장한다.

HashMap의 값의 저장 과정

HashMap은 해시 함수를 통해 '키'와 '값'이 저장되는 위치를 결정하므로, 사용자는 그 위치를 알 수 없고, 삽입되는 순서와 위치 또한 관계가 없다. 이렇게, HashMap은 이름 그대로 해싱(Hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는 데 있어서 뛰어난 성능을 보인다.

 

HashMap을 생성할 때에는 아래와 같이 키와 값의 타입을 따로 지정해주어야 한다.

HashMap<String, Integer> hashmap = new HashMap<>();

 

아래 예제를 살펴보자.

import java.util.*;
public class HashMapExample {
public static void main(String[] args) {
// HashMap 생성
HashMap<String, Integer> map = new HashMap<>();
// Entry 객체 저장
map.put("피카츄", 85);
map.put("꼬부기", 95);
map.put("야도란", 75);
map.put("파이리", 65);
map.put("피존투", 15);
// 저장된 총 Entry 수 얻기
System.out.println("총 entry 수: " + map.size());
// 객체 찾기
System.out.println("파이리 : " + map.get("파이리"));
// key를 요소로 가지는 Set을 생성 -> 아래에서 순회하기 위해 필요하다.
Set<String> keySet = map.keySet();
// keySet을 순회하면서 value를 읽어온다.
Iterator<String> keyIterator = keySet.iterator();
while(keyIterator.hasNext()) {
String key = keyIterator.next();
Integer value = map.get(key);
System.out.println(key + " : " + value);
}
// 객체 삭제
map.remove("피존투");
System.out.println("총 entry 수: " + map.size());
// Entry 객체를 요소로 가지는 Set을 생성 -> 아래에서 순회하기 위해 필요하다.
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
// entrySet을 순회하면서 value를 읽어온다.
Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
while(entryIterator.hasNext()) {
Map.Entry<String, Integer> entry = entryIterator.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " : " + value);
}
// 객체 전체 삭제
map.clear();
}
}

Map은 키와 값을 쌍으로 저장하기 때문에 iterator()를 직접 호출할 수 없다.

그 대신, keySet()이나 entrySet()메서드를 이용해 Set 형태로 반환된 컬렉션에 iterator()를 호출하여 반복자를 만든 후, 반복자를 통해 순회할 수 있다.

 

📌 HashTable

HashTable은 HashMap과 내부 구조가 동일하며, 사용 방법 또한 매우 유사하다.

HashTable과 HashMap의 차이점은 스레드와 관련이 있다.

HashTable은 쓰레드에 대해 Thread-safety하고 HashMap은 Thread-safety하지 않다.

※ Thread Safe :

스레드 안전(thread safety)은 멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 뜻한다. 보다 엄밀하게는 하나의 함수가 한 스레드로부터 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하여 동시에 함께 실행되더라도 각 스레드에서의 함수의 수행 결과가 올바로 나오는 것으로 정의한다.

 

멀티 쓰레드 환경이 아니라면 HashTable은 HashMap보다 성능이 떨어지는 단점이 있다.

댓글