11 |
|
import java.util.stream.Streams; |
12 |
|
import java.util.function.Consumer; |
13 |
|
|
14 |
– |
|
14 |
|
/** |
15 |
|
* A scalable concurrent {@link ConcurrentNavigableMap} implementation. |
16 |
|
* The map is sorted according to the {@linkplain Comparable natural |
70 |
|
* @param <V> the type of mapped values |
71 |
|
* @since 1.6 |
72 |
|
*/ |
74 |
– |
@SuppressWarnings("unchecked") |
73 |
|
public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> |
74 |
|
implements ConcurrentNavigableMap<K,V>, |
75 |
|
Cloneable, |
472 |
|
* Returns value if this node contains a valid key-value pair, |
473 |
|
* else null. |
474 |
|
* @return this node's value if it isn't a marker or header or |
475 |
< |
* is deleted, else null |
475 |
> |
* is deleted, else null. |
476 |
|
*/ |
477 |
+ |
@SuppressWarnings("unchecked") |
478 |
|
V getValidValue() { |
479 |
|
Object v = value; |
480 |
|
if (v == this || v == BASE_HEADER) |
611 |
|
* Compares using comparator or natural ordering. Used in cases |
612 |
|
* where it isn't worthwhile to use multiple code paths. |
613 |
|
*/ |
614 |
+ |
@SuppressWarnings("unchecked") |
615 |
|
int compare(K k1, K k2) throws ClassCastException { |
616 |
|
Comparator<? super K> cmp = comparator; |
617 |
|
if (cmp != null) |
787 |
|
} |
788 |
|
if (v == n || b.value == null) // b is deleted |
789 |
|
break; |
790 |
+ |
@SuppressWarnings("unchecked") V vv = (V)v; |
791 |
|
int c = key.compareTo(n.key); |
792 |
|
if (c == 0) |
793 |
< |
return (V)v; |
793 |
> |
return vv; |
794 |
|
if (c < 0) |
795 |
|
return null; |
796 |
|
b = n; |
836 |
|
n = f; |
837 |
|
continue; |
838 |
|
} |
839 |
+ |
|
840 |
|
if (c == 0) { |
841 |
< |
if (onlyIfAbsent || n.casValue(v, value)) |
842 |
< |
return (V)v; |
841 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
842 |
> |
if (onlyIfAbsent || n.casValue(vv, value)) |
843 |
> |
return vv; |
844 |
|
else |
845 |
|
break; // restart if lost race to replace value |
846 |
|
} |
860 |
|
* Adds zero or more index nodes for the given key and node. |
861 |
|
* Shared by plain and Cmp versions of put |
862 |
|
*/ |
863 |
+ |
@SuppressWarnings("unchecked") |
864 |
|
private void addIndex(K key, Node<K,V> z) { |
865 |
|
if (key == null || z == null) // don't postpone errors |
866 |
|
throw new NullPointerException(); |
1015 |
|
if (head.right == null) |
1016 |
|
tryReduceLevel(); |
1017 |
|
} |
1018 |
< |
return (V)v; |
1018 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
1019 |
> |
return vv; |
1020 |
|
} |
1021 |
|
} |
1022 |
|
} |
1097 |
|
if (!n.appendMarker(f) || !b.casNext(n, f)) |
1098 |
|
findFirst(); // retry |
1099 |
|
clearIndexToFirst(); |
1100 |
< |
return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, (V)v); |
1100 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
1101 |
> |
return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, vv); |
1102 |
|
} |
1103 |
|
} |
1104 |
|
|
1126 |
|
* Specialized variant of doRemove. |
1127 |
|
* @return null if empty, else snapshot of last entry |
1128 |
|
*/ |
1129 |
+ |
@SuppressWarnings("unchecked") |
1130 |
|
Map.Entry<K,V> doRemoveLastEntry() { |
1131 |
|
for (;;) { |
1132 |
|
Node<K,V> b = findPredecessorOfLast(); |
1388 |
|
} |
1389 |
|
if (v == n || b.value == null) // b is deleted |
1390 |
|
break; |
1391 |
+ |
@SuppressWarnings("unchecked") V vv = (V)v; |
1392 |
|
int c = cmp.compare(key, n.key); |
1393 |
|
if (c == 0) |
1394 |
< |
return (V)v; |
1394 |
> |
return vv; |
1395 |
|
if (c < 0) |
1396 |
|
return null; |
1397 |
|
b = n; |
1425 |
|
continue; |
1426 |
|
} |
1427 |
|
if (c == 0) { |
1428 |
< |
if (onlyIfAbsent || n.casValue(v, value)) |
1429 |
< |
return (V)v; |
1428 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
1429 |
> |
if (onlyIfAbsent || n.casValue(vv, value)) |
1430 |
> |
return vv; |
1431 |
|
else |
1432 |
|
break; // restart if lost race to replace value |
1433 |
|
} |
1482 |
|
if (head.right == null) |
1483 |
|
tryReduceLevel(); |
1484 |
|
} |
1485 |
< |
return (V)v; |
1485 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
1486 |
> |
return vv; |
1487 |
|
} |
1488 |
|
} |
1489 |
|
} |
1738 |
|
/** |
1739 |
|
* Reconstitutes this map from a stream (that is, deserializes it). |
1740 |
|
*/ |
1741 |
+ |
@SuppressWarnings("unchecked") |
1742 |
|
private void readObject(final java.io.ObjectInputStream s) |
1743 |
|
throws java.io.IOException, ClassNotFoundException { |
1744 |
|
// Read in the Comparator and any hidden stuff |
1990 |
|
* This is of course only appropriate if it is acceptable to use |
1991 |
|
* the same value for all additions from this view. |
1992 |
|
* |
1993 |
< |
* @param mappedValue the mapped value to use for any additions |
1993 |
> |
* @param mappedValue the mapped value to use for any |
1994 |
> |
* additions. |
1995 |
|
* @return the set view |
1996 |
|
* @throws NullPointerException if the mappedValue is null |
1997 |
|
*/ |
2150 |
|
throw new NullPointerException(); |
2151 |
|
Comparator<? super K> cmp = comparator; |
2152 |
|
for (;;) { |
2153 |
+ |
@SuppressWarnings("unchecked") |
2154 |
|
Node<K,V> n = (cmp == null) ? |
2155 |
|
findNode((Comparable<? super K>)key) : |
2156 |
|
findNodeCmp(cmp, key); |
2180 |
|
throw new NullPointerException(); |
2181 |
|
Comparator<? super K> cmp = comparator; |
2182 |
|
for (;;) { |
2183 |
+ |
@SuppressWarnings("unchecked") |
2184 |
|
Node<K,V> n = (cmp == null) ? |
2185 |
|
findNode((Comparable<? super K>)key) : |
2186 |
|
findNodeCmp(cmp, key); |
2187 |
|
if (n == null) |
2188 |
|
return null; |
2189 |
< |
Object v = n.value; |
2189 |
> |
@SuppressWarnings("unchecked") V v = (V)n.value; |
2190 |
|
if (v != null && n.casValue(v, value)) |
2191 |
< |
return (V)v; |
2191 |
> |
return v; |
2192 |
|
} |
2193 |
|
} |
2194 |
|
|
2457 |
|
break; |
2458 |
|
Object x = next.value; |
2459 |
|
if (x != null && x != next) { |
2460 |
< |
nextValue = (V) x; |
2460 |
> |
@SuppressWarnings("unchecked") V vv = (V)x; |
2461 |
> |
nextValue = vv; |
2462 |
|
break; |
2463 |
|
} |
2464 |
|
} |
2479 |
|
break; |
2480 |
|
Object x = next.value; |
2481 |
|
if (x != null && x != next) { |
2482 |
< |
nextValue = (V) x; |
2482 |
> |
@SuppressWarnings("unchecked") V vv = (V)x; |
2483 |
> |
nextValue = vv; |
2484 |
|
break; |
2485 |
|
} |
2486 |
|
} |
2577 |
|
Map.Entry<E,?> e = m.pollLastEntry(); |
2578 |
|
return (e == null) ? null : e.getKey(); |
2579 |
|
} |
2580 |
+ |
@SuppressWarnings("unchecked") |
2581 |
|
public Iterator<E> iterator() { |
2582 |
|
if (m instanceof ConcurrentSkipListMap) |
2583 |
|
return ((ConcurrentSkipListMap<E,Object>)m).keyIterator(); |
2628 |
|
public NavigableSet<E> descendingSet() { |
2629 |
|
return new KeySet<E>(m.descendingMap()); |
2630 |
|
} |
2631 |
< |
|
2632 |
< |
public Stream<E> stream() { |
2616 |
< |
int flags = Streams.STREAM_IS_DISTINCT | |
2617 |
< |
Streams.STREAM_IS_SORTED | Streams.STREAM_IS_ORDERED; |
2631 |
> |
@SuppressWarnings("unchecked") |
2632 |
> |
Spliterator<E> spliterator() { |
2633 |
|
if (m instanceof ConcurrentSkipListMap) |
2634 |
< |
return Streams.stream |
2620 |
< |
(() -> ((ConcurrentSkipListMap<E,?>)m).keySpliterator(), |
2621 |
< |
flags); |
2634 |
> |
return ((ConcurrentSkipListMap<E,?>)m).keySpliterator(); |
2635 |
|
else |
2636 |
< |
return Streams.stream |
2637 |
< |
(Streams.spliteratorUnknownSize(iterator()), flags); |
2636 |
> |
return (Spliterator<E>)((SubMap<E,?>)m).keyIterator(); |
2637 |
> |
} |
2638 |
> |
|
2639 |
> |
public Stream<E> stream() { |
2640 |
> |
return Streams.stream(spliterator()); |
2641 |
|
} |
2642 |
|
|
2643 |
|
public Stream<E> parallelStream() { |
2644 |
< |
int flags = Streams.STREAM_IS_DISTINCT | |
2629 |
< |
Streams.STREAM_IS_SORTED | Streams.STREAM_IS_ORDERED; |
2630 |
< |
if (m instanceof ConcurrentSkipListMap) |
2631 |
< |
return Streams.parallelStream |
2632 |
< |
(() -> ((ConcurrentSkipListMap<E,?>)m).keySpliterator(), |
2633 |
< |
flags); |
2634 |
< |
else |
2635 |
< |
return Streams.parallelStream |
2636 |
< |
(Streams.spliteratorUnknownSize(iterator()), flags); |
2644 |
> |
return Streams.parallelStream(spliterator()); |
2645 |
|
} |
2646 |
|
} |
2647 |
|
|
2650 |
|
Values(ConcurrentNavigableMap<?, E> map) { |
2651 |
|
m = map; |
2652 |
|
} |
2653 |
+ |
@SuppressWarnings("unchecked") |
2654 |
|
public Iterator<E> iterator() { |
2655 |
|
if (m instanceof ConcurrentSkipListMap) |
2656 |
|
return ((ConcurrentSkipListMap<?,E>)m).valueIterator(); |
2671 |
|
} |
2672 |
|
public Object[] toArray() { return toList(this).toArray(); } |
2673 |
|
public <T> T[] toArray(T[] a) { return toList(this).toArray(a); } |
2674 |
< |
|
2675 |
< |
public Stream<E> stream() { |
2667 |
< |
int flags = Streams.STREAM_IS_ORDERED; |
2674 |
> |
@SuppressWarnings("unchecked") |
2675 |
> |
Spliterator<E> spliterator() { |
2676 |
|
if (m instanceof ConcurrentSkipListMap) |
2677 |
< |
return Streams.stream |
2670 |
< |
(() -> ((ConcurrentSkipListMap<?,E>)m).valueSpliterator(), |
2671 |
< |
flags); |
2677 |
> |
return ((ConcurrentSkipListMap<?,E>)m).valueSpliterator(); |
2678 |
|
else |
2679 |
< |
return Streams.stream |
2680 |
< |
(Streams.spliteratorUnknownSize(iterator()), flags); |
2679 |
> |
return (Spliterator<E>)((SubMap<?,E>)m).valueIterator(); |
2680 |
> |
} |
2681 |
> |
|
2682 |
> |
public Stream<E> stream() { |
2683 |
> |
return Streams.stream(spliterator()); |
2684 |
|
} |
2685 |
|
|
2686 |
|
public Stream<E> parallelStream() { |
2687 |
< |
int flags = Streams.STREAM_IS_ORDERED; |
2679 |
< |
if (m instanceof ConcurrentSkipListMap) |
2680 |
< |
return Streams.parallelStream |
2681 |
< |
(() -> ((ConcurrentSkipListMap<?,E>)m).valueSpliterator(), |
2682 |
< |
flags); |
2683 |
< |
else |
2684 |
< |
return Streams.parallelStream |
2685 |
< |
(Streams.spliteratorUnknownSize(iterator()), flags); |
2687 |
> |
return Streams.parallelStream(spliterator()); |
2688 |
|
} |
2689 |
|
} |
2690 |
|
|
2693 |
|
EntrySet(ConcurrentNavigableMap<K1, V1> map) { |
2694 |
|
m = map; |
2695 |
|
} |
2696 |
< |
|
2696 |
> |
@SuppressWarnings("unchecked") |
2697 |
|
public Iterator<Map.Entry<K1,V1>> iterator() { |
2698 |
|
if (m instanceof ConcurrentSkipListMap) |
2699 |
|
return ((ConcurrentSkipListMap<K1,V1>)m).entryIterator(); |
2740 |
|
} |
2741 |
|
public Object[] toArray() { return toList(this).toArray(); } |
2742 |
|
public <T> T[] toArray(T[] a) { return toList(this).toArray(a); } |
2743 |
< |
|
2744 |
< |
@Override public Stream<Map.Entry<K1,V1>> stream() { |
2743 |
< |
int flags = Streams.STREAM_IS_ORDERED | Streams.STREAM_IS_DISTINCT; |
2743 |
> |
@SuppressWarnings("unchecked") |
2744 |
> |
Spliterator<Map.Entry<K1,V1>> spliterator() { |
2745 |
|
if (m instanceof ConcurrentSkipListMap) |
2746 |
< |
return Streams.stream |
2746 |
< |
(() -> ((ConcurrentSkipListMap<K1,V1>)m).entrySpliterator(), |
2747 |
< |
flags); |
2746 |
> |
return ((ConcurrentSkipListMap<K1,V1>)m).entrySpliterator(); |
2747 |
|
else |
2748 |
< |
return Streams.stream |
2749 |
< |
(Streams.spliteratorUnknownSize(iterator()), flags); |
2748 |
> |
return (Spliterator<Map.Entry<K1,V1>>) |
2749 |
> |
((SubMap<K1,V1>)m).entryIterator(); |
2750 |
> |
} |
2751 |
> |
|
2752 |
> |
public Stream<Map.Entry<K1,V1>> stream() { |
2753 |
> |
return Streams.stream(spliterator()); |
2754 |
|
} |
2755 |
|
|
2756 |
|
public Stream<Map.Entry<K1,V1>> parallelStream() { |
2757 |
< |
int flags = Streams.STREAM_IS_ORDERED | Streams.STREAM_IS_DISTINCT; |
2755 |
< |
if (m instanceof ConcurrentSkipListMap) |
2756 |
< |
return Streams.parallelStream |
2757 |
< |
(() -> ((ConcurrentSkipListMap<K1,V1>)m).entrySpliterator(), |
2758 |
< |
flags); |
2759 |
< |
else |
2760 |
< |
return Streams.parallelStream |
2761 |
< |
(Streams.spliteratorUnknownSize(iterator()), flags); |
2757 |
> |
return Streams.parallelStream(spliterator()); |
2758 |
|
} |
2759 |
|
|
2760 |
|
} |
3029 |
|
|
3030 |
|
public boolean containsKey(Object key) { |
3031 |
|
if (key == null) throw new NullPointerException(); |
3032 |
< |
K k = (K)key; |
3032 |
> |
@SuppressWarnings("unchecked") K k = (K)key; |
3033 |
|
return inBounds(k) && m.containsKey(k); |
3034 |
|
} |
3035 |
|
|
3036 |
|
public V get(Object key) { |
3037 |
|
if (key == null) throw new NullPointerException(); |
3038 |
< |
K k = (K)key; |
3038 |
> |
@SuppressWarnings("unchecked") K k = (K)key; |
3039 |
|
return (!inBounds(k)) ? null : m.get(k); |
3040 |
|
} |
3041 |
|
|
3045 |
|
} |
3046 |
|
|
3047 |
|
public V remove(Object key) { |
3048 |
< |
K k = (K)key; |
3048 |
> |
@SuppressWarnings("unchecked") K k = (K)key; |
3049 |
|
return (!inBounds(k)) ? null : m.remove(k); |
3050 |
|
} |
3051 |
|
|
3094 |
|
} |
3095 |
|
|
3096 |
|
public boolean remove(Object key, Object value) { |
3097 |
< |
K k = (K)key; |
3097 |
> |
@SuppressWarnings("unchecked") K k = (K)key; |
3098 |
|
return inBounds(k) && m.remove(k, value); |
3099 |
|
} |
3100 |
|
|
3298 |
|
|
3299 |
|
/** |
3300 |
|
* Variant of main Iter class to traverse through submaps. |
3301 |
+ |
* Also serves as back-up Spliterator for views |
3302 |
|
*/ |
3303 |
< |
abstract class SubMapIter<T> implements Iterator<T> { |
3303 |
> |
abstract class SubMapIter<T> implements Iterator<T>, Spliterator<T> { |
3304 |
|
/** the last node returned by next() */ |
3305 |
|
Node<K,V> lastReturned; |
3306 |
|
/** the next node to return from next(); */ |
3315 |
|
break; |
3316 |
|
Object x = next.value; |
3317 |
|
if (x != null && x != next) { |
3318 |
+ |
@SuppressWarnings("unchecked") V vv = (V)x; |
3319 |
|
if (! inBounds(next.key)) |
3320 |
|
next = null; |
3321 |
|
else |
3322 |
< |
nextValue = (V) x; |
3322 |
> |
nextValue = vv; |
3323 |
|
break; |
3324 |
|
} |
3325 |
|
} |
3346 |
|
break; |
3347 |
|
Object x = next.value; |
3348 |
|
if (x != null && x != next) { |
3349 |
+ |
@SuppressWarnings("unchecked") V vv = (V)x; |
3350 |
|
if (tooHigh(next.key)) |
3351 |
|
next = null; |
3352 |
|
else |
3353 |
< |
nextValue = (V) x; |
3353 |
> |
nextValue = vv; |
3354 |
|
break; |
3355 |
|
} |
3356 |
|
} |
3365 |
|
break; |
3366 |
|
Object x = next.value; |
3367 |
|
if (x != null && x != next) { |
3368 |
+ |
@SuppressWarnings("unchecked") V vv = (V)x; |
3369 |
|
if (tooLow(next.key)) |
3370 |
|
next = null; |
3371 |
|
else |
3372 |
< |
nextValue = (V) x; |
3372 |
> |
nextValue = vv; |
3373 |
|
break; |
3374 |
|
} |
3375 |
|
} |
3383 |
|
lastReturned = null; |
3384 |
|
} |
3385 |
|
|
3386 |
+ |
public boolean tryAdvance(Consumer<? super T> action) { |
3387 |
+ |
if (hasNext()) { |
3388 |
+ |
action.accept(next()); |
3389 |
+ |
return true; |
3390 |
+ |
} |
3391 |
+ |
return false; |
3392 |
+ |
} |
3393 |
+ |
|
3394 |
+ |
public void forEach(Consumer<? super T> action) { |
3395 |
+ |
while (hasNext()) |
3396 |
+ |
action.accept(next()); |
3397 |
+ |
} |
3398 |
|
} |
3399 |
|
|
3400 |
|
final class SubMapValueIterator extends SubMapIter<V> { |
3403 |
|
advance(); |
3404 |
|
return v; |
3405 |
|
} |
3406 |
+ |
public int characteristics() { |
3407 |
+ |
return 0; |
3408 |
+ |
} |
3409 |
|
} |
3410 |
|
|
3411 |
|
final class SubMapKeyIterator extends SubMapIter<K> { |
3414 |
|
advance(); |
3415 |
|
return n.key; |
3416 |
|
} |
3417 |
+ |
public int characteristics() { |
3418 |
+ |
return Spliterator.DISTINCT | Spliterator.ORDERED | |
3419 |
+ |
Spliterator.SORTED; |
3420 |
+ |
} |
3421 |
+ |
public final Comparator<? super K> getComparator() { |
3422 |
+ |
return SubMap.this.comparator(); |
3423 |
+ |
} |
3424 |
|
} |
3425 |
|
|
3426 |
|
final class SubMapEntryIterator extends SubMapIter<Map.Entry<K,V>> { |
3430 |
|
advance(); |
3431 |
|
return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v); |
3432 |
|
} |
3433 |
+ |
public int characteristics() { |
3434 |
+ |
return Spliterator.DISTINCT; |
3435 |
+ |
} |
3436 |
|
} |
3437 |
|
} |
3438 |
|
|
3473 |
|
* or {@code null} if additions are not supported. |
3474 |
|
* |
3475 |
|
* @return the default mapped value for additions, or {@code null} |
3476 |
< |
* if not supported |
3476 |
> |
* if not supported. |
3477 |
|
*/ |
3478 |
|
public V getMappedValue() { return value; } |
3479 |
|
|
3566 |
|
return new KeySet<K>(m.descendingMap()); |
3567 |
|
} |
3568 |
|
|
3569 |
+ |
Spliterator<K> spliterator() { |
3570 |
+ |
return m.keySpliterator(); |
3571 |
+ |
} |
3572 |
+ |
|
3573 |
|
public Stream<K> stream() { |
3574 |
< |
int flags = Streams.STREAM_IS_DISTINCT | |
3546 |
< |
Streams.STREAM_IS_SORTED | Streams.STREAM_IS_ORDERED; |
3547 |
< |
return Streams.stream(() -> m.keySpliterator(), flags); |
3574 |
> |
return Streams.stream(spliterator()); |
3575 |
|
} |
3576 |
|
|
3577 |
|
public Stream<K> parallelStream() { |
3578 |
< |
int flags = Streams.STREAM_IS_DISTINCT | |
3552 |
< |
Streams.STREAM_IS_SORTED | Streams.STREAM_IS_ORDERED; |
3553 |
< |
return Streams.parallelStream(() -> m.keySpliterator(), flags); |
3578 |
> |
return Streams.parallelStream(spliterator()); |
3579 |
|
} |
3580 |
|
|
3581 |
|
} |
3632 |
|
} |
3633 |
|
|
3634 |
|
/** Return >= 0 if key is too large (out of bounds) */ |
3635 |
+ |
@SuppressWarnings("unchecked") |
3636 |
|
final int compareBounds(K k) { |
3637 |
|
Comparator<? super K> cmp; K f; |
3638 |
|
if (k == null || (f = fence) == null) |
3644 |
|
} |
3645 |
|
|
3646 |
|
public final long estimateSize() { return (long)est; } |
3647 |
< |
public final boolean hasExactSize() { |
3622 |
< |
return est == 0 && current == null; // true only if empty |
3623 |
< |
} |
3624 |
< |
public final boolean hasExactSplits() { return false; } |
3647 |
> |
|
3648 |
|
} |
3649 |
|
|
3650 |
|
// factory methods |
3668 |
|
super(comparator, row, origin, fence, est); |
3669 |
|
} |
3670 |
|
|
3671 |
+ |
@SuppressWarnings("unchecked") |
3672 |
|
public KeySpliterator<K,V> trySplit() { |
3673 |
|
Node<K,V> e; |
3674 |
|
Comparator<? super K> cmp = comparator; |
3699 |
|
return null; |
3700 |
|
} |
3701 |
|
|
3702 |
< |
public void forEach(Consumer<? super K> block) { |
3703 |
< |
if (block == null) throw new NullPointerException(); |
3702 |
> |
public void forEach(Consumer<? super K> action) { |
3703 |
> |
if (action == null) throw new NullPointerException(); |
3704 |
|
K f = fence; |
3705 |
|
Comparator<? super K> cmp = comparator; |
3706 |
+ |
@SuppressWarnings("unchecked") |
3707 |
|
Comparable<? super K> cf = (f != null && cmp == null) ? |
3708 |
|
(Comparable<? super K>)f : null; |
3709 |
|
Node<K,V> e = current; |
3715 |
|
(f != null && cmp.compare(f, k) <= 0))) |
3716 |
|
break; |
3717 |
|
if ((v = e.value) != null && v != e) |
3718 |
< |
block.accept(k); |
3718 |
> |
action.accept(k); |
3719 |
|
} |
3720 |
|
} |
3721 |
|
|
3722 |
< |
public boolean tryAdvance(Consumer<? super K> block) { |
3723 |
< |
if (block == null) throw new NullPointerException(); |
3722 |
> |
public boolean tryAdvance(Consumer<? super K> action) { |
3723 |
> |
if (action == null) throw new NullPointerException(); |
3724 |
|
Node<K,V> e; |
3725 |
|
for (e = current; e != null; e = e.next) { |
3726 |
|
K k; Object v; |
3730 |
|
} |
3731 |
|
if ((v = e.value) != null && v != e) { |
3732 |
|
current = e.next; |
3733 |
< |
block.accept(k); |
3733 |
> |
action.accept(k); |
3734 |
|
return true; |
3735 |
|
} |
3736 |
|
} |
3737 |
|
current = e; |
3738 |
|
return false; |
3739 |
|
} |
3740 |
+ |
|
3741 |
+ |
public int characteristics() { |
3742 |
+ |
return Spliterator.DISTINCT | Spliterator.SORTED | |
3743 |
+ |
Spliterator.ORDERED | Spliterator.CONCURRENT | |
3744 |
+ |
Spliterator.NONNULL; |
3745 |
+ |
} |
3746 |
+ |
|
3747 |
+ |
public final Comparator<? super K> getComparator() { |
3748 |
+ |
return comparator; |
3749 |
+ |
} |
3750 |
|
} |
3751 |
|
|
3752 |
|
static final class ValueSpliterator<K,V> extends CSLMSpliterator<K,V> |
3757 |
|
super(comparator, row, origin, fence, est); |
3758 |
|
} |
3759 |
|
|
3760 |
+ |
@SuppressWarnings("unchecked") |
3761 |
|
public ValueSpliterator<K,V> trySplit() { |
3762 |
|
Node<K,V> e; |
3763 |
|
Comparator<? super K> cmp = comparator; |
3788 |
|
return null; |
3789 |
|
} |
3790 |
|
|
3791 |
< |
public void forEach(Consumer<? super V> block) { |
3792 |
< |
if (block == null) throw new NullPointerException(); |
3791 |
> |
public void forEach(Consumer<? super V> action) { |
3792 |
> |
if (action == null) throw new NullPointerException(); |
3793 |
|
K f = fence; |
3794 |
|
Comparator<? super K> cmp = comparator; |
3795 |
+ |
@SuppressWarnings("unchecked") |
3796 |
|
Comparable<? super K> cf = (f != null && cmp == null) ? |
3797 |
|
(Comparable<? super K>)f : null; |
3798 |
|
Node<K,V> e = current; |
3803 |
|
(cf != null ? (cf.compareTo(k) <= 0) : |
3804 |
|
(f != null && cmp.compare(f, k) <= 0))) |
3805 |
|
break; |
3806 |
< |
if ((v = e.value) != null && v != e) |
3807 |
< |
block.accept((V)v); |
3806 |
> |
if ((v = e.value) != null && v != e) { |
3807 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
3808 |
> |
action.accept(vv); |
3809 |
> |
} |
3810 |
|
} |
3811 |
|
} |
3812 |
|
|
3813 |
< |
public boolean tryAdvance(Consumer<? super V> block) { |
3814 |
< |
if (block == null) throw new NullPointerException(); |
3813 |
> |
public boolean tryAdvance(Consumer<? super V> action) { |
3814 |
> |
if (action == null) throw new NullPointerException(); |
3815 |
|
boolean advanced = false; |
3816 |
|
Node<K,V> e; |
3817 |
|
for (e = current; e != null; e = e.next) { |
3822 |
|
} |
3823 |
|
if ((v = e.value) != null && v != e) { |
3824 |
|
current = e.next; |
3825 |
< |
block.accept((V)v); |
3825 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
3826 |
> |
action.accept(vv); |
3827 |
|
return true; |
3828 |
|
} |
3829 |
|
} |
3830 |
|
current = e; |
3831 |
|
return false; |
3832 |
|
} |
3833 |
+ |
|
3834 |
+ |
public int characteristics() { |
3835 |
+ |
return Spliterator.CONCURRENT | Spliterator.NONNULL; |
3836 |
+ |
} |
3837 |
|
} |
3838 |
|
|
3839 |
|
static final class EntrySpliterator<K,V> extends CSLMSpliterator<K,V> |
3844 |
|
super(comparator, row, origin, fence, est); |
3845 |
|
} |
3846 |
|
|
3847 |
+ |
@SuppressWarnings("unchecked") |
3848 |
|
public EntrySpliterator<K,V> trySplit() { |
3849 |
|
Node<K,V> e; |
3850 |
|
Comparator<? super K> cmp = comparator; |
3876 |
|
return null; |
3877 |
|
} |
3878 |
|
|
3879 |
< |
public void forEach(Consumer<? super Map.Entry<K,V>> block) { |
3880 |
< |
if (block == null) throw new NullPointerException(); |
3879 |
> |
public void forEach(Consumer<? super Map.Entry<K,V>> action) { |
3880 |
> |
if (action == null) throw new NullPointerException(); |
3881 |
|
K f = fence; |
3882 |
|
Comparator<? super K> cmp = comparator; |
3883 |
+ |
@SuppressWarnings("unchecked") |
3884 |
|
Comparable<? super K> cf = (f != null && cmp == null) ? |
3885 |
|
(Comparable<? super K>)f : null; |
3886 |
|
Node<K,V> e = current; |
3892 |
|
(cf.compareTo(k) <= 0) : |
3893 |
|
(f != null && cmp.compare(f, k) <= 0))) |
3894 |
|
break; |
3895 |
< |
if ((v = e.value) != null && v != e) |
3896 |
< |
block.accept |
3897 |
< |
(new AbstractMap.SimpleImmutableEntry<K,V>(k, (V)v)); |
3895 |
> |
if ((v = e.value) != null && v != e) { |
3896 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
3897 |
> |
action.accept |
3898 |
> |
(new AbstractMap.SimpleImmutableEntry<K,V>(k, vv)); |
3899 |
> |
} |
3900 |
|
} |
3901 |
|
} |
3902 |
|
|
3903 |
< |
public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> block) { |
3904 |
< |
if (block == null) throw new NullPointerException(); |
3903 |
> |
public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) { |
3904 |
> |
if (action == null) throw new NullPointerException(); |
3905 |
|
Node<K,V> e; |
3906 |
|
for (e = current; e != null; e = e.next) { |
3907 |
|
K k; Object v; |
3911 |
|
} |
3912 |
|
if ((v = e.value) != null && v != e) { |
3913 |
|
current = e.next; |
3914 |
< |
block.accept |
3915 |
< |
(new AbstractMap.SimpleImmutableEntry<K,V>(k, (V)v)); |
3914 |
> |
@SuppressWarnings("unchecked") V vv = (V)v; |
3915 |
> |
action.accept |
3916 |
> |
(new AbstractMap.SimpleImmutableEntry<K,V>(k, vv)); |
3917 |
|
return true; |
3918 |
|
} |
3919 |
|
} |
3920 |
|
current = e; |
3921 |
|
return false; |
3922 |
|
} |
3923 |
+ |
|
3924 |
+ |
public int characteristics() { |
3925 |
+ |
return Spliterator.DISTINCT | Spliterator.SORTED | |
3926 |
+ |
Spliterator.ORDERED | Spliterator.CONCURRENT | |
3927 |
+ |
Spliterator.NONNULL; |
3928 |
+ |
} |
3929 |
|
} |
3930 |
|
|
3931 |
|
// Unsafe mechanics |