--- a/jdk/src/share/classes/java/util/HashMap.java Wed Apr 17 14:39:04 2013 -0400
+++ b/jdk/src/share/classes/java/util/HashMap.java Wed Apr 17 11:34:31 2013 +0200
@@ -1230,6 +1230,14 @@
public void clear() {
HashMap.this.clear();
}
+
+ public Spliterator<K> spliterator() {
+ if (HashMap.this.getClass() == HashMap.class)
+ return new KeySpliterator<K,V>(HashMap.this, 0, -1, 0, 0);
+ else
+ return Spliterators.spliterator
+ (this, Spliterator.SIZED | Spliterator.DISTINCT);
+ }
}
/**
@@ -1263,6 +1271,14 @@
public void clear() {
HashMap.this.clear();
}
+
+ public Spliterator<V> spliterator() {
+ if (HashMap.this.getClass() == HashMap.class)
+ return new ValueSpliterator<K,V>(HashMap.this, 0, -1, 0, 0);
+ else
+ return Spliterators.spliterator
+ (this, Spliterator.SIZED);
+ }
}
/**
@@ -1310,6 +1326,14 @@
public void clear() {
HashMap.this.clear();
}
+
+ public Spliterator<Map.Entry<K,V>> spliterator() {
+ if (HashMap.this.getClass() == HashMap.class)
+ return new EntrySpliterator<K,V>(HashMap.this, 0, -1, 0, 0);
+ else
+ return Spliterators.spliterator
+ (this, Spliterator.SIZED | Spliterator.DISTINCT);
+ }
}
/**
@@ -1406,4 +1430,257 @@
// These methods are used when serializing HashSets
int capacity() { return table.length; }
float loadFactor() { return loadFactor; }
+
+ /**
+ * Standin until HM overhaul; based loosely on Weak and Identity HM.
+ */
+ static class HashMapSpliterator<K,V> {
+ final HashMap<K,V> map;
+ HashMap.Entry<K,V> current; // current node
+ int index; // current index, modified on advance/split
+ int fence; // one past last index
+ int est; // size estimate
+ int expectedModCount; // for comodification checks
+
+ HashMapSpliterator(HashMap<K,V> m, int origin,
+ int fence, int est,
+ int expectedModCount) {
+ this.map = m;
+ this.index = origin;
+ this.fence = fence;
+ this.est = est;
+ this.expectedModCount = expectedModCount;
+ }
+
+ final int getFence() { // initialize fence and size on first use
+ int hi;
+ if ((hi = fence) < 0) {
+ HashMap<K,V> m = map;
+ est = m.size;
+ expectedModCount = m.modCount;
+ hi = fence = m.table.length;
+ }
+ return hi;
+ }
+
+ public final long estimateSize() {
+ getFence(); // force init
+ return (long) est;
+ }
+ }
+
+ static final class KeySpliterator<K,V>
+ extends HashMapSpliterator<K,V>
+ implements Spliterator<K> {
+ KeySpliterator(HashMap<K,V> m, int origin, int fence, int est,
+ int expectedModCount) {
+ super(m, origin, fence, est, expectedModCount);
+ }
+
+ public KeySpliterator<K,V> trySplit() {
+ int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
+ return (lo >= mid || current != null) ? null :
+ new KeySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
+ expectedModCount);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void forEachRemaining(Consumer<? super K> action) {
+ int i, hi, mc;
+ if (action == null)
+ throw new NullPointerException();
+ HashMap<K,V> m = map;
+ HashMap.Entry<K,V>[] tab = (HashMap.Entry<K,V>[])m.table;
+ if ((hi = fence) < 0) {
+ mc = expectedModCount = m.modCount;
+ hi = fence = tab.length;
+ }
+ else
+ mc = expectedModCount;
+ if (tab.length >= hi && (i = index) >= 0 && i < (index = hi)) {
+ HashMap.Entry<K,V> p = current;
+ do {
+ if (p == null)
+ p = tab[i++];
+ else {
+ action.accept(p.getKey());
+ p = p.next;
+ }
+ } while (p != null || i < hi);
+ if (m.modCount != mc)
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean tryAdvance(Consumer<? super K> action) {
+ int hi;
+ if (action == null)
+ throw new NullPointerException();
+ HashMap.Entry<K,V>[] tab = (HashMap.Entry<K,V>[])map.table;
+ if (tab.length >= (hi = getFence()) && index >= 0) {
+ while (current != null || index < hi) {
+ if (current == null)
+ current = tab[index++];
+ else {
+ K k = current.getKey();
+ current = current.next;
+ action.accept(k);
+ if (map.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public int characteristics() {
+ return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
+ Spliterator.DISTINCT;
+ }
+ }
+
+ static final class ValueSpliterator<K,V>
+ extends HashMapSpliterator<K,V>
+ implements Spliterator<V> {
+ ValueSpliterator(HashMap<K,V> m, int origin, int fence, int est,
+ int expectedModCount) {
+ super(m, origin, fence, est, expectedModCount);
+ }
+
+ public ValueSpliterator<K,V> trySplit() {
+ int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
+ return (lo >= mid || current != null) ? null :
+ new ValueSpliterator<K,V>(map, lo, index = mid, est >>>= 1,
+ expectedModCount);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void forEachRemaining(Consumer<? super V> action) {
+ int i, hi, mc;
+ if (action == null)
+ throw new NullPointerException();
+ HashMap<K,V> m = map;
+ HashMap.Entry<K,V>[] tab = (HashMap.Entry<K,V>[])m.table;
+ if ((hi = fence) < 0) {
+ mc = expectedModCount = m.modCount;
+ hi = fence = tab.length;
+ }
+ else
+ mc = expectedModCount;
+ if (tab.length >= hi && (i = index) >= 0 && i < (index = hi)) {
+ HashMap.Entry<K,V> p = current;
+ do {
+ if (p == null)
+ p = tab[i++];
+ else {
+ action.accept(p.getValue());
+ p = p.next;
+ }
+ } while (p != null || i < hi);
+ if (m.modCount != mc)
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean tryAdvance(Consumer<? super V> action) {
+ int hi;
+ if (action == null)
+ throw new NullPointerException();
+ HashMap.Entry<K,V>[] tab = (HashMap.Entry<K,V>[])map.table;
+ if (tab.length >= (hi = getFence()) && index >= 0) {
+ while (current != null || index < hi) {
+ if (current == null)
+ current = tab[index++];
+ else {
+ V v = current.getValue();
+ current = current.next;
+ action.accept(v);
+ if (map.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public int characteristics() {
+ return (fence < 0 || est == map.size ? Spliterator.SIZED : 0);
+ }
+ }
+
+ static final class EntrySpliterator<K,V>
+ extends HashMapSpliterator<K,V>
+ implements Spliterator<Map.Entry<K,V>> {
+ EntrySpliterator(HashMap<K,V> m, int origin, int fence, int est,
+ int expectedModCount) {
+ super(m, origin, fence, est, expectedModCount);
+ }
+
+ public EntrySpliterator<K,V> trySplit() {
+ int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
+ return (lo >= mid || current != null) ? null :
+ new EntrySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
+ expectedModCount);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {
+ int i, hi, mc;
+ if (action == null)
+ throw new NullPointerException();
+ HashMap<K,V> m = map;
+ HashMap.Entry<K,V>[] tab = (HashMap.Entry<K,V>[])m.table;
+ if ((hi = fence) < 0) {
+ mc = expectedModCount = m.modCount;
+ hi = fence = tab.length;
+ }
+ else
+ mc = expectedModCount;
+ if (tab.length >= hi && (i = index) >= 0 && i < (index = hi)) {
+ HashMap.Entry<K,V> p = current;
+ do {
+ if (p == null)
+ p = tab[i++];
+ else {
+ action.accept(p);
+ p = p.next;
+ }
+ } while (p != null || i < hi);
+ if (m.modCount != mc)
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {
+ int hi;
+ if (action == null)
+ throw new NullPointerException();
+ HashMap.Entry<K,V>[] tab = (HashMap.Entry<K,V>[])map.table;
+ if (tab.length >= (hi = getFence()) && index >= 0) {
+ while (current != null || index < hi) {
+ if (current == null)
+ current = tab[index++];
+ else {
+ HashMap.Entry<K,V> e = current;
+ current = current.next;
+ action.accept(e);
+ if (map.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public int characteristics() {
+ return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
+ Spliterator.DISTINCT;
+ }
+ }
}