src/share/classes/java/util/HashMap.java
Print this page
rev 7360 : 8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap
Reviewed-by: forax, duigou, psandoz
Contributed-by: Mike Duigou <mike.duigou@oracle.com>, Remi Forax <forax@univ-mlv.fr>
*** 27,36 ****
--- 27,37 ----
import java.io.*;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.ThreadLocalRandom;
+ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
*** 1303,1312 ****
--- 1304,1415 ----
}
// optimized implementations of default methods in Map
@Override
+ public void forEach(BiConsumer<? super K, ? super V> action) {
+ Objects.requireNonNull(action);
+ final int expectedModCount = modCount;
+ if (nullKeyEntry != null) {
+ forEachNullKey(expectedModCount, action);
+ }
+ Object[] tab = this.table;
+ for (int index = 0; index < tab.length; index++) {
+ Object item = tab[index];
+ if (item == null) {
+ continue;
+ }
+ if (item instanceof HashMap.TreeBin) {
+ eachTreeNode(expectedModCount, ((TreeBin)item).first, action);
+ continue;
+ }
+ @SuppressWarnings("unchecked")
+ Entry<K, V> entry = (Entry<K, V>)item;
+ while (entry != null) {
+ action.accept(entry.key, entry.value);
+ entry = (Entry<K, V>)entry.next;
+
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+ }
+
+ private void eachTreeNode(int expectedModCount, TreeNode<K, V> node, BiConsumer<? super K, ? super V> action) {
+ while (node != null) {
+ @SuppressWarnings("unchecked")
+ Entry<K, V> entry = (Entry<K, V>)node.entry;
+ action.accept(entry.key, entry.value);
+ node = (TreeNode<K, V>)entry.next;
+
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+
+ private void forEachNullKey(int expectedModCount, BiConsumer<? super K, ? super V> action) {
+ action.accept(null, nullKeyEntry.value);
+
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ Objects.requireNonNull(function);
+ final int expectedModCount = modCount;
+ if (nullKeyEntry != null) {
+ replaceforNullKey(expectedModCount, function);
+ }
+ Object[] tab = this.table;
+ for (int index = 0; index < tab.length; index++) {
+ Object item = tab[index];
+ if (item == null) {
+ continue;
+ }
+ if (item instanceof HashMap.TreeBin) {
+ replaceEachTreeNode(expectedModCount, ((TreeBin)item).first, function);
+ continue;
+ }
+ @SuppressWarnings("unchecked")
+ Entry<K, V> entry = (Entry<K, V>)item;
+ while (entry != null) {
+ entry.value = function.apply(entry.key, entry.value);
+ entry = (Entry<K, V>)entry.next;
+
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+ }
+
+ private void replaceEachTreeNode(int expectedModCount, TreeNode<K, V> node, BiFunction<? super K, ? super V, ? extends V> function) {
+ while (node != null) {
+ @SuppressWarnings("unchecked")
+ Entry<K, V> entry = (Entry<K, V>)node.entry;
+ entry.value = function.apply(entry.key, entry.value);
+ node = (TreeNode<K, V>)entry.next;
+
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+
+ private void replaceforNullKey(int expectedModCount, BiFunction<? super K, ? super V, ? extends V> function) {
+ nullKeyEntry.value = function.apply(null, nullKeyEntry.value);
+
+ if (expectedModCount != modCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ @Override
public V putIfAbsent(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null) {
*** 2295,2310 ****
Entry<K,V> retVal;
if (e == null)
throw new NoSuchElementException();
! if (e instanceof Entry) {
! retVal = (Entry<K,V>)e;
! next = ((Entry<K,V>)e).next;
! } else { // TreeBin
retVal = (Entry<K,V>)((TreeNode)e).entry;
next = retVal.next;
}
if (next == null) { // Move to next bin
findNextBin();
}
--- 2398,2413 ----
Entry<K,V> retVal;
if (e == null)
throw new NoSuchElementException();
! if (e instanceof TreeNode) { // TreeBin
retVal = (Entry<K,V>)((TreeNode)e).entry;
next = retVal.next;
+ } else {
+ retVal = (Entry<K,V>)e;
+ next = ((Entry<K,V>)e).next;
}
if (next == null) { // Move to next bin
findNextBin();
}