0. ๋ค์ด๊ฐ๋ฉฐ
HashMap ์๋ฃํ์ ์ฌ์ฉํ๋ฉฐ ํ์ด์ผ ํ๋ ๋ฌธ์ ์ค, compute
๋ฅผ ์ธ ์ผ์ด ์์๋๋ฐ, ๊ฐ์๊ธฐ ํด๋น ๋ด์ฉ์ด ์๊ฐ์ด ๋์ง ์์์ ๋ค์ ์ ๋ฆฌํ๋ค. HashMap์ compute
๋ putIfPresent
, putIfAbsent
๋ฑ์ ์ ๋ถ ํฌ๊ดํ๋ฉฐ ๋ด๊ฐ ํ๊ณ ์ถ์ ์์
์ ๋๋ถ๋ถ์ ํ ์ ์์ด์ ํธํ๋ค. ์ด๋ฒ์ compute์ ๋ํด ์์ธํ ์์๋ณด๊ฒ ๋ค.
1. ํํ
V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction);
// ex
map.compute(key, (key,oldValue) -> {... return newValue});
๋ฐํํ
: ๋ฐํํ์V
๋ ํ์ฌ ํจ์๋ฅผ ๋ถ๋ฅธ Map์ value์ ์๋ฃํ์ ๋ปํ๋ค. ๋ง์ฝ HashMap<Integer, Integer> ์๋ค๋ฉด V๋ Integer๊ฐ ๋๋ ํ์์ด๋ค.์ธ์
: ์ธ์๋ค์ ๋ค์ฌ๋ค ๋ณด๋ฉด, Key, Remapping Function ํํ๋ก ์ด๋ฃจ์ด์ง ๊ฒ์ ๋ณผ ์ ์๋ค.Key
: value์ ๋ง์ฐฌ๊ฐ์ง๋ก, ํด๋น ํจ์๋ฅผ ๋ถ๋ฅธ HashMap์ Key์ด๋ค.remappingfunction
: key์ value๋ฅผ ๊ฐ์ ธ์ ์ ์ํ ์ฐ์ฐ๊ณผ์ ์ ๊ฑฐ์น ํ ๋ค์ ํด๋น key์ value๋ก ์ฌ ๋งคํ๋๋ค๋ ์๋ฏธ์์ remappingfunction์ด๋ผ ๋ช ๋ช ๋์๋ค.
remappingfunction์ ์ธ์๋ ๋ค์key
์oldvalue
๋ก ๋๋๋ค.oldValue
: ํด๋น key๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ธฐ์กด์ value ๊ฐ์ ์๋ฏธํ๋ค.newValue
: remapping ํจ์์์ ๋ฐํํ๋ ๊ฐ์ผ๋ก compute ์์ฒด์ ๋ฐํ๊ฐ์ด์ key์ new value๊ฐ ๋๋ค.
ex
๋ ์์์ ์ค๋ช
ํ ๋ด์ฉ๋ค์ด ์ค์ ๋ก ์ด๋ป๊ฒ ์ฐ์ด๋์ง์ ๋ํ ์์ ์ด๋ค.
2. ํน์ง
1๏ธโฃcompute์ ์ธ์๋ก ๋ฃ์ key๊ฐ map์ ์กด์ฌํ์ง ์๋ ๊ฐ์ด๋ผ๋ฉด ์ ๊ท ์ฝ์ ํด์ค๋ค.
map.compute(key, (key,oldValue) -> {... return newValue});
์ฌ๊ธฐ์ k
๊ฐ ๊ธฐ์กด์ map์ ์๋ ๊ฐ์ด์ด๋ ๊ด์ฐฎ๋ค. ๋ง์ฝ ์๋ ๊ฐ์ด๋ผ๋ฉด map์ <key, newValue> ์์ด ์ ๊ท ์ฝ์
๋๋ค.
(key๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ ๊ฐ์ด๋ฉด newValue๋ก ๋ฎ์ด์ฐ๊ธฐ ๋๋ค.)
2๏ธโฃ ์ธ์๋ก ๋ค์ด์จ Key๋ฅผ Map์์ ์ญ์ ๊ฐ๋ฅํ๋ค.
remappingfunction์์ return null
์ ํ๋ค๋ฉด, ์ธ์๋ก ๋ค์ด์จ key๋ฅผ ์ญ์ ํ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค.
3. ํจ์ ์์ ๋ค์ฌ๋ค๋ณด์.
๋ฐ์ ํจ์๋ Java 17์ ๊ธฐ์ค์ผ๋ก ํ๋ค.
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Node<K,V> e; // ํ์ฌ Key์ ํด๋นํ๋ ์ํธ๋ฆฌ๋
ธ๋
V oldValue; // ์ด์ ๊ฐ
int hash = hash(key); // key์ ํด์๊ฐ
int binCount = 0; // ๋์ผ ํด์๊ฐ์ ๊ฐ์ง ์์ ์ ์ฅํ๋ ๋ฒํท์ด ๋ช ๊ฐ์ ๋
ธ๋๊ฐ ์๋์ง ์ธ๋ ์ฉ๋
// table: ์ค์ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๋ Node<K,V>[] ๋ฐฐ์ด
// tab: ์ด table ๋ฐฐ์ด์ ๋ก์ปฌ ๋ณ์๋ก ์ฎ๊ฒจ๋์ (์ต์ ํ ๋ชฉ์ )
// ๋ง์ฝ ์์ง ๋ฐฐ์ด์ด ์ด๊ธฐํ๋์ง ์์๊ฑฐ๋ ๊ธธ์ด๊ฐ 0์ด๋ฉด resize()๋ฅผ ํธ์ถํด์ ์ด๊ธฐํํ๊ณ , ๊ธธ์ด ๊ฐ์ ธ์ด
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// ๋์ผ Hash ๊ฐ์ ๊ฐ์ง Bucket ๋ด์์ ์ฐ๋ฆฌ๊ฐ ์ฐพ๋ key-value ์์ ์ฐพ๋ ๊ณผ์
// i = (n - 1) & hash → ๋ฒํท์ ์ธ๋ฑ์ค ๊ณ์ฐ (๋นํธ ์ฐ์ฐ์ผ๋ก ๋ชจ๋๋ก ์ฐ์ฐ)
// ํด๋น ๋ฒํท ์ธ๋ฑ์ค์ ์ํธ๋ฆฌ๊ฐ ์กด์ฌํ๋ค๋ฉด (key ์ถฉ๋ ๋ฑ)
if ((e = tab[i = (n - 1) & hash]) != null) {
Node<K,V> node = null;
K k;
V v;
// ์ฐ๊ฒฐ๋ฆฌ์คํธ or ํธ๋ฆฌ๋ก ์ฐ๊ฒฐ๋ ์ํธ๋ฆฌ๋ค ์ค์์ ์ํ๋ key๋ฅผ ์ฐพ๋ ๊ณผ์
do {
// ๊ฐ์ hash์ด๊ณ , key ์์ฒด๋ ๊ฐ์ผ๋ฉด ํด๋น ๋
ธ๋ ์ฐพ์
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
oldValue = e.value; // oldValue ์ฎ๊ฒจ ๋ด๊ธฐ
node = e; // Entry ์ฎ๊ฒจ ๋ด๊ธฐ
break;
}
} while ((e = e.next) != null); // ์์ผ๋ฉด ๊ณ์ ๋ฒํท๋ด์์ ์ฐ๊ฒฐ๋ ๋ค์ ๋
ธ๋๋ก ์ด๋
// remappingFunction ์คํํด์ ์ ๊ฐ์ ๊ณ์ฐํจ
V newValue = remappingFunction.apply(key, oldValue);
// null ์ด ์๋๋ฉด ๋ฎ์ด์ฐ๊ธฐ, null ์ด๋ฉด ํด๋น entrySet์ Map์์ ์ง์ด๋ค.
if (newValue != null) {
node.value = newValue;
} else {
removeNode(hash, key, null, false, true);
}
return newValue;
} else {
// key๊ฐ ์์ ๋ ์ฆ key๊ฐ HashMap์ ์ ์ฅ๋์ง ์์ ๊ฒฝ์ฐ, oldvalue = null๋ก ๋ฃ๊ณ ์งํ
V newValue = remappingFunction.apply(key, null);
if (newValue != null)
putVal(hash, key, newValue, false, true);
return newValue;
}
}
๋ค์๊ณผ ๊ฐ์ ๊ณผ์ ์ผ๋ก ๋๋์ด์ง ๊ฒ์ ์ ์ ์๋ค.
- (1) map ๋ด์์ ์ธ์๋ก ๋ค์ด์จ Key๊ฐ์ ํด๋นํ๋ EntrySet ์ฐพ๊ธฐ (์์ผ๋ฉด ๊ทธ๋ฅ null๋ก ๋๊ณ ๋์ด๊ฐ)
- (2) remappingFunction ํจ์ ํ์ฉํด์ ๊ณ์ฐ
- ๊ฒฐ๊ณผ๊ฐ null ์ด๋ฉด ํด๋น entrySet์ map ๋ด์์ ์ง์ด๋ค.
- ๊ฒฐ๊ณผ๊ฐ null ์๋๋ฉด, ํด๋น key์ value๋ฅผ newValue๋ก ๋ฎ์ด์ด๋ค.
- ๊ธฐ์กด์ ์๋ key ๊ฐ์ด๋ฉด <key, value> ์์ผ๋ก ์ ์ฅํ๋ค.
4. ๊ฒฐ๋ก
compute๋ฅผ ์ฐ๋ฉด, putIfAbsent, putIfPresent๋ฅผ ๋ฐ๋ก ์ฐ์ง ์๊ณ ํ ๋ฒ์ ํด๊ฒฐํ ์ ์์ ๋ฟ๋๋ฌ, ํ์์๋ key,value ์์ ์ง์๋ฒ๋ฆด ์๋ ์์ด์ ํธํ๋ค. ๋ฐ๋ฉด remappingFunction ๋์ ํญ์ value๊ฐ ๋ฐํ๊ฐ์ผ๋ก ๋ณ๊ฒฝ๋๋ฏ๋ก, getOrDefault ์ญํ ์ ํ์ง ๋ชปํ๋ค.