๋ชฉ์ฐจ
์ง๊ธ๊น์ง List์ Set์ ๊ตฌํ์ฒด๋ค์ ์ดํด๋ดค๋ค๋ฉด, ์ด์ Key-Value ๊ตฌ์กฐ์ Map ์ธํฐํ์ด์ค ๊ตฌํ์ฒด๋ค์ ๋น๊ตํด ๋ณผ ์ฐจ๋ก์ ๋๋ค.
Map์ ๋ฐ์ดํฐ๋ฅผ ํค-๊ฐ ์์ผ๋ก ์ ์ฅํ๋ ์๋ฃ๊ตฌ์กฐ๋ก, ๋น ๋ฅธ ๊ฒ์๊ณผ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ๊ด๋ฆฌ์ ํ์์ ์ ๋๋ค.
์ด๋ฒ ๊ธ์์๋ Java Map ์ธํฐํ์ด์ค์ ๊ธฐ๋ณธ ๊ฐ๋ ๋ถํฐ, ๋ํ ๊ตฌํ์ฒด์ธ HashMap, TreeMap, LinkedHashMap์ ํน์ง๊ณผ ์ฑ๋ฅ์ ํ๋์ ๋น๊ตํด๋ณด๊ฒ ์ต๋๋ค.
๐๏ธ Map ์ธํฐํ์ด์ค๋?
Map์ Key-Value ํํ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์๋ฃ๊ตฌ์กฐ๋ก, Key๋ ์ค๋ณต์ด ๋ถ๊ฐ๋ฅํ๋ฉฐ Value๋ ์ค๋ณต์ด ๊ฐ๋ฅํฉ๋๋ค.
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1000); // Key: "Apple", Value: 1000
map.put("Banana", 1500); // Key: "Banana", Value: 1500
Integer price = map.get("Apple"); // 1000 ๋ฐํ
์ฃผ์ ํน์ง
- Key๋ ์ค๋ณต ๋ถ๊ฐ, Value๋ ์ค๋ณต ๊ฐ๋ฅ
- Key๋ฅผ ํตํ ๋น ๋ฅธ ๊ฒ์ ๊ฐ๋ฅ
- null ํ์ฉ ์ฌ๋ถ์ ์์ ๋ณด์ฅ ์ฌ๋ถ๋ ๊ตฌํ์ฒด๋ง๋ค ๋ค๋ฆ
Map์ ํต์ฌ ๋ฉ์๋
๋ฉ์๋ | ์ค๋ช |
put(K key, V value) | ํค-๊ฐ ์ ์ถ๊ฐ ๋๋ ์์ |
get(Object key) | ํค๋ก ๊ฐ ์กฐํ |
remove(Object key) | ํค-๊ฐ ์ ์ญ์ |
containsKey() | ํค ์กด์ฌ ์ฌ๋ถ ํ์ธ |
keySet() | ๋ชจ๋ ํค ๋ฐํ |
values() | ๋ชจ๋ ๊ฐ ๋ฐํ |
entrySet() | ๋ชจ๋ ํค-๊ฐ ์ ๋ฐํ |
๐ HashMap vs TreeMap vs LinkedHashMap
HashMap
HashMap์ ํด์ ํ ์ด๋ธ ๊ธฐ๋ฐ์ Map์ผ๋ก ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๊ตฌํ์ฒด์ ๋๋ค.
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Banana", 1500);
hashMap.put("Apple", 1000);
hashMap.put("Cherry", 2000);
System.out.println(hashMap);
// ์ถ๋ ฅ ์: {Cherry=2000, Apple=1000, Banana=1500} - ์์ ๋ณด์ฅ ์๋จ
- ์์ ๋ณด์ฅ ์๋จ: ํด์๊ฐ์ ๋ฐ๋ผ ์ ์ฅ ์์ ๊ฒฐ์
- ๋น ๋ฅธ ์ฑ๋ฅ: ํ๊ท O(1) ์๊ฐ๋ณต์ก๋
- null ํ์ฉ: Key์ Value ๋ชจ๋ null ๊ฐ๋ฅ (Key๋ ํ๋๋ง)
- ๋น๋๊ธฐ: ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์์ ํ์ง ์์
TreeMap
TreeMap์ ์ด์ง ๊ฒ์ ํธ๋ฆฌ(Red-Black Tree) ๊ธฐ๋ฐ์ผ๋ก ์๋ ์ ๋ ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Banana", 1500);
treeMap.put("Apple", 1000);
treeMap.put("Cherry", 2000);
System.out.println(treeMap);
// ์ถ๋ ฅ: {Apple=1000, Banana=1500, Cherry=2000} - ํค ๊ธฐ์ค ์๋ ์ ๋ ฌ
- ์๋ ์ ๋ ฌ: ํค ๊ธฐ์ค์ผ๋ก ์๋ ์ ๋ ฌ ์ ์ง
- NavigableMap ๊ตฌํ: ๋ฒ์ ๊ฒ์, ๊ทผ์ ํค ์ฐพ๊ธฐ ๊ฐ๋ฅ
- null ๋ถ๊ฐ: Key์ null ์ฌ์ฉ ๋ถ๊ฐ (Value๋ ๊ฐ๋ฅ)
- ๋๋ฆฐ ์ฑ๋ฅ: O(log n) ์๊ฐ๋ณต์ก๋
LinkedHashMap
LinkedHashMap์ ํด์ ํ ์ด๋ธ + ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๊ตฌ์กฐ๋ก, ์ ๋ ฅ ์์๋ฅผ ์ ์งํฉ๋๋ค.
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("Banana", 1500);
linkedHashMap.put("Apple", 1000);
linkedHashMap.put("Cherry", 2000);
System.out.println(linkedHashMap);
// ์ถ๋ ฅ: {Banana=1500, Apple=1000, Cherry=2000} - ์ฝ์
์์ ์ ์ง
- ์ฝ์ ์์ ์ ์ง: ์์๊ฐ ์ถ๊ฐ๋ ์์๋ฅผ ๊ธฐ์ต
- HashMap๊ณผ ์ ์ฌํ ์ฑ๋ฅ: ํ๊ท O(1) ์๊ฐ๋ณต์ก๋
- null ํ์ฉ: Key์ Value ๋ชจ๋ null ๊ฐ๋ฅ
- ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ: ์์ ์ ์ง๋ฅผ ์ํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ์ค๋ฒํค๋
์ฑ๋ฅ๊ณผ ํน์ง ๋น๊ต
ํน์ฑ | HashMap | TreeMap | LinkedHashMap |
์์ ๋ณด์ฅ | โ | โ (์ ๋ ฌ) | โ (์ฝ์ ์์) |
์ ๋ ฌ | โ | โ (์๋) | โ |
null Key | โ (1๊ฐ) | โ | โ (1๊ฐ) |
null Value | โ | โ | โ |
๊ฒ์/์ฝ์ /์ญ์ | O(1) ํ๊ท | O(log n) | O(1) ํ๊ท |
๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ | ์ ์ | ์ค๊ฐ | ๋ง์ |
์ฌ์ฉ ๋ชฉ์ | ๋น ๋ฅธ ๊ฒ์ | ์ ๋ ฌ/๋ฒ์ ๊ฒ์ | ์์ ์ ์ง, LRU ์บ์ ๋ฑ |
๐ป ์ค์ ํ์ฉ ์์
1๏ธโฃ HashMap - ์ฌ์ฉ์ ์ ๋ณด ๊ด๋ฆฌ
Map<String, String> userMap = new HashMap<>();
userMap.put("user001", "๊น์๋ฐ");
userMap.put("user002", "์ด์ฝ๋ฉ");
String userName = userMap.get("user001"); // O(1) ๋น ๋ฅธ ๊ฒ์
2๏ธโฃ TreeMap - ์ฑ์ ๊ด๋ฆฌ ์์คํ
Map<String, Integer> scoreMap = new TreeMap<>();
scoreMap.put("ํ๊ธธ๋", 85);
scoreMap.put("๊น์ํฌ", 92);
System.out.println(scoreMap); // Key ๊ธฐ์ค ์ ๋ ฌ
๊ณ ๊ธ ๊ธฐ๋ฅ ์์
TreeMap<String, Integer> treeScoreMap = (TreeMap<String, Integer>) scoreMap;
String firstStudent = treeScoreMap.firstKey(); // ๊ฐ์ฅ ์์ Key
String higherStudent = treeScoreMap.higherKey("๊น์ํฌ"); // ๋ฐ๋ก ๋ค์ Key
3๏ธโฃ LinkedHashMap - ์น ์บ์ ์์คํ (LRU)
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int maxSize;
public LRUCache(int maxSize) {
super(16, 0.75f, true); // accessOrder=true
this.maxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
}
// ์ฌ์ฉ ์
LRUCache<String, String> cache = new LRUCache<>(3);
cache.put("page1", "๋ด์ฉ1");
cache.put("page2", "๋ด์ฉ2");
cache.get("page1"); // page1์ด ์ต๊ทผ์ผ๋ก ์ด๋
cache.put("page4", "๋ด์ฉ4"); // ์ค๋๋ page2 ์ ๊ฑฐ
๐ null ํ์ฉ ์ฌ๋ถ์ ๋์์ฑ ์ฃผ์
- HashMap: Key, Value ๋ชจ๋ null ํ์ฉ
- TreeMap: Key๋ null ๋ถ๊ฐ (์์ธ ๋ฐ์), Value๋ null ํ์ฉ
- LinkedHashMap: Key, Value ๋ชจ๋ null ํ์ฉ
๋์์ฑ ์ฒ๋ฆฌ๋ ์ง์ ๋๊ธฐํํ๊ฑฐ๋ ConcurrentHashMap์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
Map<String, Integer> safeMap = Collections.synchronizedMap(new HashMap<>());
// ํน์
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
๐ ๏ธ Map ์ ํ ๊ฐ์ด๋
- ๐ธ HashMap → ๊ฐ์ฅ ์ผ๋ฐ์ , ๋น ๋ฅธ ์ฑ๋ฅ์ด ํ์ํ ๋
- ๐ธ TreeMap → Key ์ ๋ ฌ/๋ฒ์ ๊ฒ์์ด ํ์ํ ๋
- ๐ธ LinkedHashMap → ์ฝ์ ์์ ์ ์ง, ์บ์ ๊ตฌํ
์ค๋ฌด์์๋ 90% ์ด์์ด HashMap์ผ๋ก๋ ์ถฉ๋ถํฉ๋๋ค. ํน์ํ ๊ฒฝ์ฐ์๋ง TreeMap, LinkedHashMap์ ์ ํํด๋ ๋ฌด๋ฐฉํฉ๋๋ค.
๐ ๋ง๋ฌด๋ฆฌ
์ด๋ฒ ๊ธ์์๋ Java์ Map ์ธํฐํ์ด์ค์ ๊ทธ ๋ํ ๊ตฌํ์ฒด(HashMap, TreeMap, LinkedHashMap)์ ๊ตฌ์กฐ์ ์ฑ๋ฅ์ ๋น๊ตํด ๋ดค์ต๋๋ค.
Map์ ์๋ฐ ๊ฐ๋ฐ์์ ๋ฐ์ดํฐ ์ ์ฅ์ ํต์ฌ ๋๊ตฌ์ธ ๋งํผ, ๊ฐ ๊ตฌํ์ฒด์ ํน์ง์ ์ ์ดํดํ๊ณ ์ํฉ์ ๋ง๊ฒ ์ ํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋ค์ ๊ธ์์๋ Iterator์ Stream API๋ฅผ ํ์ฉํ ์ปฌ๋ ์ ์ํ ๋ฐฉ๋ฒ์ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
๊ถ๊ธํ ์ ์ด๋ ๋ ์๊ณ ์ถ์ ๋ถ๋ถ์ด ์๋ค๋ฉด ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์ธ์! ๐