컬렉션(Collection)[0] - Collection에 대하여 (완료)
컬렉션(Collection)[1] - List에 대하여 (완료)
컬렉션(Collection)[2] - Map에 대하여 (현재)
컬렉션(Collection)[3] - Set에 대하여 (예정)
Map 인터페이스는 Collection 인가?
간단하게 설명드리자면 Map은 Collection이 아니고, Collection 역시 Map이 아닙니다.
Java의 Map 인터페이스는 Collection 인터페이스를 직접적으로 상속하고 있지 않습니다.
Map과 Collection은 각각 별도의 최상위 인터페이스로 설계되어 있습니다.
따라서 Map 인터페이스는 Collection 인터페이스의 멤버들을 직접적으로 상속하지 않으며,
Map과 Collection은 서로 다른 계층 구조에 속합니다.
하지만, 둘 다 Java의 Collection Framework에서 데이터 구조를 관리하는 곳에 사용되는 중요한 인터페이스들입니다.
그래서 Map 인터페이스 같은 경우에는 Collection으로 분류됩니다.
요약
- Map 인터페이스는 Collection 인터페이스를 상속하는 것이 아닙니다
- Map은 Iterable을 직접적으로 구현하고 있지는 않습니다.
- 하지만 구현체인 HashMap, TreeMap, LinkedHashMap 등에서 entrySet() 메서드를 사용함으로 써 Set 인터페이스를 반환합니다.
- Set 은 Iterable을 상속하므로 Map과 Collection은 모두 Iterable 인터페이스를 구현하고 있기 때문에, 두 인터페이스를 모두 순회할 수 있습니다.
Map
Key-Value 쌍으로 데이터를 저장하는 자료구조입니다.
각 Key는 Unique 한 값을 가져야 하며, 해당 Key에 대응하는 Value를 저장합니다.
Map 인터페이스는put(Key, Value), get(Key), remove(Key) 등의 메서드를 제공함으로써 데이터를 추가, 검색, 삭제할 수 있습니다.
Map의 대표적인 구현체로는 HashMap, TreeMap, LinkedHashMap 등이 존재합니다.
Map 은 데이터를 효율적으로 검색하고 저장하는 것에 매우 유용하며, 특히 데이터를 Key를 통해 빠르게 검색해야 할 때 사용 됩니다.
HashMap 과 TreeMap 의 비교
HashMap
Hash Table(해시 테이블)을 사용하여 데이터를 저장하며, Key의 순서를 보장하지 않습니다.
평균적으로 O(1)의 시간복잡도를 가지지만, 최악의 경우 O(n)까지 증가할 수 있습니다.
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
// HashMap 생성
Map<String, Integer> hashMap = new HashMap<>();
// 요소 추가
hashMap.put("apple", 1);
hashMap.put("banana", 2);
hashMap.put("orange", 3);
hashMap.put("grape", 4);
// 요소 접근
System.out.println("apple의 값: " + hashMap.get("apple"));
// 요소 삭제
hashMap.remove("orange");
// 모든 요소 출력
System.out.println("<< HashMap의 내용 >>");
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println("Key: " + key + ", Value: " + value);
}
}
}
각각의 예시에서는 put() 메서드를 사용하여 요소들을 추가하고, get() 메서드로 특정 Key에 대응하는 값 가져오며,
remove() 메서드로 요소를 삭제하였습니다. 또한 entrySet() 메서드를 활용하여 모든 요소들을 순회하여 출력하였습니다.
TreeMap
이진 검색 트리를 사용하여 데이터를 저장하며, Key의 순서를 유지하고 정렬합니다.
데이터 추가 및 검색이 O(log N)의 시간 복잡도를 가집니다.
import java.util.TreeMap;
import java.util.Map;
public class TreeMapExample {
public static void main(String[] args) {
// TreeMap 생성
Map<String, Integer> treeMap = new TreeMap<>();
// 요소 추가
treeMap.put("apple", 1);
treeMap.put("banana", 2);
treeMap.put("orange", 3);
treeMap.put("grape", 4);
// 요소 접근
System.out.println("banana의 값: " + treeMap.get("banana"));
// 요소 삭제
treeMap.remove("orange");
// 모든 요소 출력
System.out.println("<< TreeMap의 내용 >>");
for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println("Key: " + key + ", Value: " + value);
}
}
}
Map 인터페이스의 메서드 활용
- put(Key, Value) : Key - Value 쌍을 Map에 추가합니다.
import java.util.HashMap;
import java.util.Map;
public class PutExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
System.out.println(map); // 출력: {apple=1, banana=2, orange=3}
}
}
- get (Key) : Key에 해당하는 Value를 반환합니다.
import java.util.HashMap;
import java.util.Map;
public class GetExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
int value = map.get("apple");
System.out.println("apple의 값: " + value); // 출력: apple의 값: 1
}
}
- remove(Key) : Key에 해당하는 Key-Value 쌍을 제거합니다.
import java.util.HashMap;
import java.util.Map;
public class RemoveExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
map.remove("banana");
System.out.println(map); // 출력: {apple=1, orange=3}
}
}
- containsKey(Key) : Key의 존재 여부를 확인합니다.
import java.util.HashMap;
import java.util.Map;
public class ContainsKeyExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
boolean containsKey = map.containsKey("apple");
System.out.println("apple이 Map에 포함되어 있나요? " + containsKey); // 출력: apple이 Map에 포함되어 있나요? true
}
}
- keySet() : Map의 모든 Key 반환합니다.
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class KeySetExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
Set<String> keys = map.keySet();
System.out.println("Map의 Key들: " + keys); // 출력: Map의 Key들: [apple, banana, orange]
}
}
- values() : Map의 모든 Value를 반환합니다.
import java.util.HashMap;
import java.util.Map;
import java.util.Collection;
public class ValuesExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
Collection<Integer> values = map.values();
System.out.println("Map의 모든 값들: " + values); // 출력: Map의 모든 값들: [1, 2, 3]
}
}
Map에 대하여 알면 좋은 것들
Map의 Key 정렬
Java Map 인터페이스에는 Key를 기준으로 정렬하는 기능을 제공하는 구현체인 TreeMap이 있습니다.
TreeMap 은 Key들을 기본적으로 자연적인 순서로 정렬하며,
사용자 정의 정렬 기준을 제공하기 위해 Comparator을 활용할 수도 있습니다. ( Comparator에 대해서는 추후 포스팅 예정입니다.)
Map의 성능과 최적화
Map 인터페이스의 구현체들은 서로 다른 성능을 가지고 있습니다.
HashMap은 해시테이블을 사용하여 데이터를 저장하기 때문에 데이터 추가, 검색, 삭제에 평균적으로 O(1)의 시간 복잡도를 가지지만, 최악의 경우 O(n)까지 증가할 수 있습니다.
이때, 성능을 초기화하기 위해 초기 용량(capacity)을 적절하게 설정해주어야 합니다.
import java.util.HashMap;
import java.util.Map;
public class HashMapOptimizationExample {
public static void main(String[] args) {
// 초기 용량을 100으로 설정
Map<String, Integer> hashMap = new HashMap<>(100);
// 데이터 추가, 검색, 삭제 등의 동작
}
}
TreeMap은 이진 검색트리를 사용하여 데이터를 저장하기 때문에 데이터 추가, 검색, 삭제에 O(log n)의 시간복잡도를 가집니다.
TreeMap 은 성능을 최적화려면 균형 잡힌 트리를 유지하는 것이 중요합니다.
Map의 반복
Map의 인터페이스를 순회하는 방법으로는 entrySet() 메서드를 활용하는 방법이 가장 효율적입니다.
이 entrySet()은 Map의 모든 key-Value 쌍들을 Set의 형태로 반환해 줍니다.
import java.util.HashMap;
import java.util.Map;
public class MapIterationExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
// entrySet()을 사용하여 Map의 모든 Key-Value 쌍 순회
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println("Key: " + key + ", Value: " + value);
}
}
}
위의 예시에서는 entrySet()을 사용하여 Map의 Key , Value 쌍을 entrySet()으로 가져온 뒤, 향상된 for-each 문을 사용하여 순회하고 있습니다.
이처럼 Map은 Key를 통해 Value를 빠르게 검색하고 관리하기 때문에, 반복 작업에 있어서도 매우 유용하게 사용될 수 있습니다.
Map의 중복처리
Map 은 특성상 Key 가 중복되지 않도록 유일해야 합니다.
따라서 이미 존재하는 Key에 put() 메서드를 사용해서 Value를 입력한다면 갱신이 되기에 주의해야 합니다.
'JAVA' 카테고리의 다른 글
[JAVA] 일반 for문과 향상된 for문의 차이와 진실 Feat.Iterator (5) | 2023.07.29 |
---|---|
ObjectCopyHelper 만들기 (DTO,VO를 Entity로 ) (0) | 2023.07.28 |
[JAVA] 컬렉션(Collection)[1]- List에 대하여 (0) | 2023.07.26 |
[JAVA] 컬렉션(Collection)[0]- Collection에 대하여 (0) | 2023.07.26 |
FormData에 객체 배열(object[])을 담을 수 있는 방법 (0) | 2023.07.25 |