https://www.acmicpc.net/problem/1620
26 5
Bulbasaur
Ivysaur
Venusaur
Charmander
Charmeleon
Charizard
Squirtle
Wartortle
Blastoise
Caterpie
Metapod
Butterfree
Weedle
Kakuna
Beedrill
Pidgey
Pidgeotto
Pidgeot
Rattata
Raticate
Spearow
Fearow
Ekans
Arbok
Pikachu
Raichu
25
Raichu
3
Pidgey
Kakuna
Pikachu
26
Venusaur
16
14
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
Map<String, String> pokemons = new HashMap<>();
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int pokeNum = 1;
while (N-- > 0) {
String value = br.readLine();
pokemons.put(String.valueOf(pokeNum), value);
pokemons.put(value, String.valueOf(pokeNum));
pokeNum++;
}
StringBuilder sb = new StringBuilder();
while (M-- > 0) {
String findValue = br.readLine();
sb.append(pokemons.get(findValue)).append("\n");
}
System.out.println(sb);
}
}
내부 배열 table ( 각 Node 가 하나의 버킷이 된다. )
transient Node<K,V>[] table;
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V> {
// 핵심 데이터 구조: Node 배열
transient Node<K,V>[] table;
// Node 클래스 정의
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
// ... 기타 메서드
}
Node<K,V> next;
를 통해put 연산
// putVal 메서드 (간략화)
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
// 충돌 처리 로직...
}
// ... 기타 로직
return null;
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
해시 충돌은
Node 의 next 변수가 다음 리스트의 주소를 가지고 있기에, 해당 구조는 링크드 리스트이며,
만약
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
*TREEIFY_THRESHOLD
이상의 노드가 존재하면 ⇒ 자바11 기준 8개*버킷안의 노드를
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
else if ((e = tab[index = (n - 1) & hash]) != null) {
TreeNode<K,V> hd = null, tl = null;
do {
TreeNode<K,V> p = replacementTreeNode(e, null);
if (tl == null)
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
} while ((e = e.next) != null);
if ((tab[index] = hd) != null)
hd.treeify(tab);
}
}
TreeNode 트리구조로 내부 노드를 변경한다.
get
// get 메서드
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}