54 |
|
* |
55 |
|
* @author Doug Lea |
56 |
|
* @param <K> the type of keys maintained by this map |
57 |
< |
* @param <V> the type of mapped values |
57 |
> |
* @param <V> the type of mapped values |
58 |
|
*/ |
59 |
< |
public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> |
59 |
> |
public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> |
60 |
|
implements ConcurrentNavigableMap<K,V>, |
61 |
< |
Cloneable, |
61 |
> |
Cloneable, |
62 |
|
java.io.Serializable { |
63 |
|
/* |
64 |
|
* This class implements a tree-like two-dimensionally linked skip |
72 |
|
* possible list with 2 levels of index: |
73 |
|
* |
74 |
|
* Head nodes Index nodes |
75 |
< |
* +-+ right +-+ +-+ |
75 |
> |
* +-+ right +-+ +-+ |
76 |
|
* |2|---------------->| |--------------------->| |->null |
77 |
< |
* +-+ +-+ +-+ |
77 |
> |
* +-+ +-+ +-+ |
78 |
|
* | down | | |
79 |
|
* v v v |
80 |
< |
* +-+ +-+ +-+ +-+ +-+ +-+ |
80 |
> |
* +-+ +-+ +-+ +-+ +-+ +-+ |
81 |
|
* |1|----------->| |->| |------>| |----------->| |------>| |->null |
82 |
< |
* +-+ +-+ +-+ +-+ +-+ +-+ |
82 |
> |
* +-+ +-+ +-+ +-+ +-+ +-+ |
83 |
|
* v | | | | | |
84 |
|
* Nodes next v v v v v |
85 |
< |
* +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ |
85 |
> |
* +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ |
86 |
|
* | |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null |
87 |
< |
* +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ |
87 |
> |
* +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ |
88 |
|
* |
89 |
|
* The base lists use a variant of the HM linked ordered set |
90 |
|
* algorithm. See Tim Harris, "A pragmatic implementation of |
143 |
|
* Here's the sequence of events for a deletion of node n with |
144 |
|
* predecessor b and successor f, initially: |
145 |
|
* |
146 |
< |
* +------+ +------+ +------+ |
146 |
> |
* +------+ +------+ +------+ |
147 |
|
* ... | b |------>| n |----->| f | ... |
148 |
< |
* +------+ +------+ +------+ |
148 |
> |
* +------+ +------+ +------+ |
149 |
|
* |
150 |
|
* 1. CAS n's value field from non-null to null. |
151 |
|
* From this point on, no public operations encountering |
159 |
|
* |
160 |
|
* +------+ +------+ +------+ +------+ |
161 |
|
* ... | b |------>| n |----->|marker|------>| f | ... |
162 |
< |
* +------+ +------+ +------+ +------+ |
162 |
> |
* +------+ +------+ +------+ +------+ |
163 |
|
* |
164 |
|
* 3. CAS b's next pointer over both n and its marker. |
165 |
|
* From this point on, no new traversals will encounter n, |
166 |
|
* and it can eventually be GCed. |
167 |
|
* +------+ +------+ |
168 |
|
* ... | b |----------------------------------->| f | ... |
169 |
< |
* +------+ +------+ |
170 |
< |
* |
169 |
> |
* +------+ +------+ |
170 |
> |
* |
171 |
|
* A failure at step 1 leads to simple retry due to a lost race |
172 |
|
* with another operation. Steps 2-3 can fail because some other |
173 |
|
* thread noticed during a traversal a node with null value and |
186 |
|
* nodes. This doesn't change the basic algorithm except for the |
187 |
|
* need to make sure base traversals start at predecessors (here, |
188 |
|
* b) that are not (structurally) deleted, otherwise retrying |
189 |
< |
* after processing the deletion. |
189 |
> |
* after processing the deletion. |
190 |
|
* |
191 |
|
* Index levels are maintained as lists with volatile next fields, |
192 |
|
* using CAS to link and unlink. Races are allowed in index-list |
290 |
|
|
291 |
|
/** |
292 |
|
* Special value used to identify base-level header |
293 |
< |
*/ |
293 |
> |
*/ |
294 |
|
private static final Object BASE_HEADER = new Object(); |
295 |
|
|
296 |
|
/** |
297 |
< |
* The topmost head index of the skiplist. |
297 |
> |
* The topmost head index of the skiplist. |
298 |
|
*/ |
299 |
|
private transient volatile HeadIndex<K,V> head; |
300 |
|
|
329 |
|
*/ |
330 |
|
final void initialize() { |
331 |
|
keySet = null; |
332 |
< |
entrySet = null; |
332 |
> |
entrySet = null; |
333 |
|
values = null; |
334 |
|
descendingEntrySet = null; |
335 |
|
descendingKeySet = null; |
339 |
|
} |
340 |
|
|
341 |
|
/** Updater for casHead */ |
342 |
< |
private static final |
343 |
< |
AtomicReferenceFieldUpdater<ConcurrentSkipListMap, HeadIndex> |
342 |
> |
private static final |
343 |
> |
AtomicReferenceFieldUpdater<ConcurrentSkipListMap, HeadIndex> |
344 |
|
headUpdater = AtomicReferenceFieldUpdater.newUpdater |
345 |
|
(ConcurrentSkipListMap.class, HeadIndex.class, "head"); |
346 |
|
|
388 |
|
} |
389 |
|
|
390 |
|
/** Updater for casNext */ |
391 |
< |
static final AtomicReferenceFieldUpdater<Node, Node> |
391 |
> |
static final AtomicReferenceFieldUpdater<Node, Node> |
392 |
|
nextUpdater = AtomicReferenceFieldUpdater.newUpdater |
393 |
|
(Node.class, Node.class, "next"); |
394 |
|
|
395 |
|
/** Updater for casValue */ |
396 |
< |
static final AtomicReferenceFieldUpdater<Node, Object> |
396 |
> |
static final AtomicReferenceFieldUpdater<Node, Object> |
397 |
|
valueUpdater = AtomicReferenceFieldUpdater.newUpdater |
398 |
|
(Node.class, Object.class, "value"); |
399 |
|
|
464 |
|
|
465 |
|
/** |
466 |
|
* Return value if this node contains a valid key-value pair, |
467 |
< |
* else null. |
467 |
> |
* else null. |
468 |
|
* @return this node's value if it isn't a marker or header or |
469 |
|
* is deleted, else null. |
470 |
|
*/ |
506 |
|
|
507 |
|
/** |
508 |
|
* Creates index node with given values |
509 |
< |
*/ |
509 |
> |
*/ |
510 |
|
Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) { |
511 |
|
this.node = node; |
512 |
|
this.key = node.key; |
515 |
|
} |
516 |
|
|
517 |
|
/** Updater for casRight */ |
518 |
< |
static final AtomicReferenceFieldUpdater<Index, Index> |
518 |
> |
static final AtomicReferenceFieldUpdater<Index, Index> |
519 |
|
rightUpdater = AtomicReferenceFieldUpdater.newUpdater |
520 |
|
(Index.class, Index.class, "right"); |
521 |
|
|
544 |
|
*/ |
545 |
|
final boolean link(Index<K,V> succ, Index<K,V> newSucc) { |
546 |
|
Node<K,V> n = node; |
547 |
< |
newSucc.right = succ; |
547 |
> |
newSucc.right = succ; |
548 |
|
return n.value != null && casRight(succ, newSucc); |
549 |
|
} |
550 |
|
|
571 |
|
super(node, down, right); |
572 |
|
this.level = level; |
573 |
|
} |
574 |
< |
} |
574 |
> |
} |
575 |
|
|
576 |
|
/* ---------------- Comparison utilities -------------- */ |
577 |
|
|
607 |
|
* cast key as Comparator, which may cause ClassCastException, |
608 |
|
* which is propagated back to caller. |
609 |
|
*/ |
610 |
< |
private Comparable<K> comparable(Object key) throws ClassCastException { |
611 |
< |
if (key == null) |
610 |
> |
private Comparable<? super K> comparable(Object key) throws ClassCastException { |
611 |
> |
if (key == null) |
612 |
|
throw new NullPointerException(); |
613 |
< |
return (comparator != null) |
614 |
< |
? new ComparableUsingComparator(key, comparator) |
613 |
> |
return (comparator != null) |
614 |
> |
? new ComparableUsingComparator(key, comparator) |
615 |
|
: (Comparable<K>)key; |
616 |
|
} |
617 |
|
|
633 |
|
* fence are null. Needed mainly in submap operations. |
634 |
|
*/ |
635 |
|
boolean inHalfOpenRange(K key, K least, K fence) { |
636 |
< |
if (key == null) |
636 |
> |
if (key == null) |
637 |
|
throw new NullPointerException(); |
638 |
|
return ((least == null || compare(key, least) >= 0) && |
639 |
|
(fence == null || compare(key, fence) < 0)); |
644 |
|
* or equal to fence. Needed mainly in submap operations. |
645 |
|
*/ |
646 |
|
boolean inOpenRange(K key, K least, K fence) { |
647 |
< |
if (key == null) |
647 |
> |
if (key == null) |
648 |
|
throw new NullPointerException(); |
649 |
|
return ((least == null || compare(key, least) >= 0) && |
650 |
|
(fence == null || compare(key, fence) <= 0)); |
658 |
|
* unlinks indexes to deleted nodes found along the way. Callers |
659 |
|
* rely on this side-effect of clearing indices to deleted nodes. |
660 |
|
* @param key the key |
661 |
< |
* @return a predecessor of key |
661 |
> |
* @return a predecessor of key |
662 |
|
*/ |
663 |
< |
private Node<K,V> findPredecessor(Comparable<K> key) { |
663 |
> |
private Node<K,V> findPredecessor(Comparable<? super K> key) { |
664 |
|
for (;;) { |
665 |
|
Index<K,V> q = head; |
666 |
|
for (;;) { |
677 |
|
continue; |
678 |
|
} |
679 |
|
} |
680 |
< |
if ((d = q.down) != null) |
680 |
> |
if ((d = q.down) != null) |
681 |
|
q = d; |
682 |
|
else |
683 |
|
return q.node; |
707 |
|
* here because doing so would not usually outweigh cost of |
708 |
|
* restarting. |
709 |
|
* |
710 |
< |
* (3) n is a marker or n's predecessor's value field is null, |
710 |
> |
* (3) n is a marker or n's predecessor's value field is null, |
711 |
|
* indicating (among other possibilities) that |
712 |
|
* findPredecessor returned a deleted node. We can't unlink |
713 |
|
* the node because we don't know its predecessor, so rely |
725 |
|
* findLast. They can't easily share code because each uses the |
726 |
|
* reads of fields held in locals occurring in the orders they |
727 |
|
* were performed. |
728 |
< |
* |
728 |
> |
* |
729 |
|
* @param key the key |
730 |
|
* @return node holding key, or null if no such. |
731 |
|
*/ |
732 |
< |
private Node<K,V> findNode(Comparable<K> key) { |
732 |
> |
private Node<K,V> findNode(Comparable<? super K> key) { |
733 |
|
for (;;) { |
734 |
|
Node<K,V> b = findPredecessor(key); |
735 |
|
Node<K,V> n = b.next; |
736 |
|
for (;;) { |
737 |
< |
if (n == null) |
737 |
> |
if (n == null) |
738 |
|
return null; |
739 |
|
Node<K,V> f = n.next; |
740 |
|
if (n != b.next) // inconsistent read |
749 |
|
int c = key.compareTo(n.key); |
750 |
|
if (c < 0) |
751 |
|
return null; |
752 |
< |
if (c == 0) |
752 |
> |
if (c == 0) |
753 |
|
return n; |
754 |
|
b = n; |
755 |
|
n = f; |
757 |
|
} |
758 |
|
} |
759 |
|
|
760 |
< |
/** |
760 |
> |
/** |
761 |
|
* Specialized variant of findNode to perform Map.get. Does a weak |
762 |
|
* traversal, not bothering to fix any deleted index nodes, |
763 |
|
* returning early if it happens to see key in index, and passing |
770 |
|
* @return the value, or null if absent |
771 |
|
*/ |
772 |
|
private V doGet(Object okey) { |
773 |
< |
Comparable<K> key = comparable(okey); |
773 |
> |
Comparable<? super K> key = comparable(okey); |
774 |
|
K bound = null; |
775 |
|
Index<K,V> q = head; |
776 |
|
for (;;) { |
777 |
|
K rk; |
778 |
|
Index<K,V> d, r; |
779 |
< |
if ((r = q.right) != null && |
779 |
> |
if ((r = q.right) != null && |
780 |
|
(rk = r.key) != null && rk != bound) { |
781 |
|
int c = key.compareTo(rk); |
782 |
|
if (c > 0) { |
789 |
|
} |
790 |
|
bound = rk; |
791 |
|
} |
792 |
< |
if ((d = q.down) != null) |
792 |
> |
if ((d = q.down) != null) |
793 |
|
q = d; |
794 |
|
else { |
795 |
|
for (Node<K,V> n = q.node.next; n != null; n = n.next) { |
815 |
|
* @param key the key |
816 |
|
* @return the value, or null if absent |
817 |
|
*/ |
818 |
< |
private V getUsingFindNode(Comparable<K> key) { |
818 |
> |
private V getUsingFindNode(Comparable<? super K> key) { |
819 |
|
/* |
820 |
|
* Loop needed here and elsewhere in case value field goes |
821 |
|
* null just as it is about to be returned, in which case we |
836 |
|
/** |
837 |
|
* Main insertion method. Adds element if not present, or |
838 |
|
* replaces value if present and onlyIfAbsent is false. |
839 |
< |
* @param kkey the key |
839 |
> |
* @param kkey the key |
840 |
|
* @param value the value that must be associated with key |
841 |
|
* @param onlyIfAbsent if should not insert if already present |
842 |
|
* @return the old value, or null if newly inserted |
843 |
|
*/ |
844 |
|
private V doPut(K kkey, V value, boolean onlyIfAbsent) { |
845 |
< |
Comparable<K> key = comparable(kkey); |
845 |
> |
Comparable<? super K> key = comparable(kkey); |
846 |
|
for (;;) { |
847 |
|
Node<K,V> b = findPredecessor(key); |
848 |
|
Node<K,V> n = b.next; |
872 |
|
} |
873 |
|
// else c < 0; fall through |
874 |
|
} |
875 |
< |
|
875 |
> |
|
876 |
|
Node<K,V> z = new Node<K,V>(kkey, value, n); |
877 |
< |
if (!b.casNext(n, z)) |
877 |
> |
if (!b.casNext(n, z)) |
878 |
|
break; // restart if lost race to append to b |
879 |
< |
int level = randomLevel(); |
880 |
< |
if (level > 0) |
879 |
> |
int level = randomLevel(); |
880 |
> |
if (level > 0) |
881 |
|
insertIndex(z, level); |
882 |
|
return null; |
883 |
|
} |
899 |
|
int level = 0; |
900 |
|
int r = randomSeed; |
901 |
|
randomSeed = r * 134775813 + 1; |
902 |
< |
if (r < 0) { |
903 |
< |
while ((r <<= 1) > 0) |
902 |
> |
if (r < 0) { |
903 |
> |
while ((r <<= 1) > 0) |
904 |
|
++level; |
905 |
|
} |
906 |
|
return level; |
933 |
|
level = max + 1; |
934 |
|
Index<K,V>[] idxs = (Index<K,V>[])new Index[level+1]; |
935 |
|
Index<K,V> idx = null; |
936 |
< |
for (int i = 1; i <= level; ++i) |
936 |
> |
for (int i = 1; i <= level; ++i) |
937 |
|
idxs[i] = idx = new Index<K,V>(z, idx, null); |
938 |
|
|
939 |
|
HeadIndex<K,V> oldh; |
947 |
|
} |
948 |
|
HeadIndex<K,V> newh = oldh; |
949 |
|
Node<K,V> oldbase = oldh.node; |
950 |
< |
for (int j = oldLevel+1; j <= level; ++j) |
950 |
> |
for (int j = oldLevel+1; j <= level; ++j) |
951 |
|
newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j); |
952 |
|
if (casHead(oldh, newh)) { |
953 |
|
k = oldLevel; |
968 |
|
private void addIndex(Index<K,V> idx, HeadIndex<K,V> h, int indexLevel) { |
969 |
|
// Track next level to insert in case of retries |
970 |
|
int insertionLevel = indexLevel; |
971 |
< |
Comparable<K> key = comparable(idx.key); |
971 |
> |
Comparable<? super K> key = comparable(idx.key); |
972 |
|
|
973 |
|
// Similar to findPredecessor, but adding index nodes along |
974 |
|
// path to key. |
985 |
|
if (q.unlink(r)) |
986 |
|
continue; |
987 |
|
else |
988 |
< |
break; |
988 |
> |
break; |
989 |
|
} |
990 |
|
if (c > 0) { |
991 |
|
q = r; |
999 |
|
findNode(key); // cleans up |
1000 |
|
return; |
1001 |
|
} |
1002 |
< |
if (!q.link(r, t)) |
1002 |
> |
if (!q.link(r, t)) |
1003 |
|
break; // restart |
1004 |
|
if (--insertionLevel == 0) { |
1005 |
|
// need final deletion check before return |
1006 |
< |
if (t.indexesDeletedNode()) |
1007 |
< |
findNode(key); |
1006 |
> |
if (t.indexesDeletedNode()) |
1007 |
> |
findNode(key); |
1008 |
|
return; |
1009 |
|
} |
1010 |
|
} |
1011 |
|
|
1012 |
< |
if (j > insertionLevel && j <= indexLevel) |
1012 |
> |
if (j > insertionLevel && j <= indexLevel) |
1013 |
|
t = t.down; |
1014 |
|
q = q.down; |
1015 |
|
--j; |
1031 |
|
* index nodes because it might be the case that some or all |
1032 |
|
* indexes hadn't been inserted yet for this node during initial |
1033 |
|
* search for it, and we'd like to ensure lack of garbage |
1034 |
< |
* retention, so must call to be sure. |
1034 |
> |
* retention, so must call to be sure. |
1035 |
|
* |
1036 |
|
* @param okey the key |
1037 |
|
* @param value if non-null, the value that must be |
1039 |
|
* @return the node, or null if not found |
1040 |
|
*/ |
1041 |
|
private V doRemove(Object okey, Object value) { |
1042 |
< |
Comparable<K> key = comparable(okey); |
1043 |
< |
for (;;) { |
1042 |
> |
Comparable<? super K> key = comparable(okey); |
1043 |
> |
for (;;) { |
1044 |
|
Node<K,V> b = findPredecessor(key); |
1045 |
|
Node<K,V> n = b.next; |
1046 |
|
for (;;) { |
1047 |
< |
if (n == null) |
1047 |
> |
if (n == null) |
1048 |
|
return null; |
1049 |
|
Node<K,V> f = n.next; |
1050 |
|
if (n != b.next) // inconsistent read |
1064 |
|
n = f; |
1065 |
|
continue; |
1066 |
|
} |
1067 |
< |
if (value != null && !value.equals(v)) |
1068 |
< |
return null; |
1069 |
< |
if (!n.casValue(v, null)) |
1067 |
> |
if (value != null && !value.equals(v)) |
1068 |
> |
return null; |
1069 |
> |
if (!n.casValue(v, null)) |
1070 |
|
break; |
1071 |
< |
if (!n.appendMarker(f) || !b.casNext(n, f)) |
1071 |
> |
if (!n.appendMarker(f) || !b.casNext(n, f)) |
1072 |
|
findNode(key); // Retry via findNode |
1073 |
|
else { |
1074 |
|
findPredecessor(key); // Clean index |
1075 |
< |
if (head.right == null) |
1075 |
> |
if (head.right == null) |
1076 |
|
tryReduceLevel(); |
1077 |
|
} |
1078 |
|
return (V)v; |
1105 |
|
HeadIndex<K,V> d; |
1106 |
|
HeadIndex<K,V> e; |
1107 |
|
if (h.level > 3 && |
1108 |
< |
(d = (HeadIndex<K,V>)h.down) != null && |
1109 |
< |
(e = (HeadIndex<K,V>)d.down) != null && |
1110 |
< |
e.right == null && |
1111 |
< |
d.right == null && |
1108 |
> |
(d = (HeadIndex<K,V>)h.down) != null && |
1109 |
> |
(e = (HeadIndex<K,V>)d.down) != null && |
1110 |
> |
e.right == null && |
1111 |
> |
d.right == null && |
1112 |
|
h.right == null && |
1113 |
|
casHead(h, d) && // try to set |
1114 |
|
h.right != null) // recheck |
1134 |
|
Node<K,V> n = b.next; |
1135 |
|
if (n == null) |
1136 |
|
return null; |
1137 |
< |
if (n.value != null) |
1137 |
> |
if (n.value != null) |
1138 |
|
return n; |
1139 |
|
n.helpDelete(b, n.next); |
1140 |
|
} |
1141 |
|
} |
1142 |
|
|
1143 |
|
/** |
1144 |
< |
* Remove first entry; return either its key or a snapshot. |
1144 |
> |
* Remove first entry; return either its key or a snapshot. |
1145 |
|
* @param keyOnly if true return key, else return SimpleImmutableEntry |
1146 |
|
* (This is a little ugly, but avoids code duplication.) |
1147 |
|
* @return null if empty, first key if keyOnly true, else key,value entry |
1148 |
|
*/ |
1149 |
|
Object doRemoveFirst(boolean keyOnly) { |
1150 |
< |
for (;;) { |
1150 |
> |
for (;;) { |
1151 |
|
Node<K,V> b = head.node; |
1152 |
|
Node<K,V> n = b.next; |
1153 |
< |
if (n == null) |
1153 |
> |
if (n == null) |
1154 |
|
return null; |
1155 |
|
Node<K,V> f = n.next; |
1156 |
|
if (n != b.next) |
1183 |
|
for (;;) { |
1184 |
|
Index<K,V> r = q.right; |
1185 |
|
if (r != null && r.indexesDeletedNode() && !q.unlink(r)) |
1186 |
< |
break; |
1186 |
> |
break; |
1187 |
|
if ((q = q.down) == null) { |
1188 |
< |
if (head.right == null) |
1188 |
> |
if (head.right == null) |
1189 |
|
tryReduceLevel(); |
1190 |
|
return; |
1191 |
|
} |
1194 |
|
} |
1195 |
|
|
1196 |
|
/** |
1197 |
< |
* Remove first entry; return key or null if empty. |
1197 |
> |
* Remove first entry; return key or null if empty. |
1198 |
|
*/ |
1199 |
|
K pollFirstKey() { |
1200 |
|
return (K)doRemoveFirst(true); |
1219 |
|
if (r.indexesDeletedNode()) { |
1220 |
|
q.unlink(r); |
1221 |
|
q = head; // restart |
1222 |
< |
} |
1222 |
> |
} |
1223 |
|
else |
1224 |
|
q = r; |
1225 |
|
} else if ((d = q.down) != null) { |
1228 |
|
Node<K,V> b = q.node; |
1229 |
|
Node<K,V> n = b.next; |
1230 |
|
for (;;) { |
1231 |
< |
if (n == null) |
1231 |
> |
if (n == null) |
1232 |
|
return (b.isBaseHeader())? null : b; |
1233 |
|
Node<K,V> f = n.next; // inconsistent read |
1234 |
|
if (n != b.next) |
1255 |
|
* @return null if empty, last key if keyOnly true, else key,value entry |
1256 |
|
*/ |
1257 |
|
Object doRemoveLast(boolean keyOnly) { |
1258 |
< |
for (;;) { |
1258 |
> |
for (;;) { |
1259 |
|
Node<K,V> b = findPredecessorOfLast(); |
1260 |
|
Node<K,V> n = b.next; |
1261 |
|
if (n == null) { |
1262 |
|
if (b.isBaseHeader()) // empty |
1263 |
|
return null; |
1264 |
< |
else |
1264 |
> |
else |
1265 |
|
continue; // all b's successors are deleted; retry |
1266 |
|
} |
1267 |
|
for (;;) { |
1280 |
|
n = f; |
1281 |
|
continue; |
1282 |
|
} |
1283 |
< |
if (!n.casValue(v, null)) |
1283 |
> |
if (!n.casValue(v, null)) |
1284 |
|
break; |
1285 |
|
K key = n.key; |
1286 |
< |
Comparable<K> ck = comparable(key); |
1287 |
< |
if (!n.appendMarker(f) || !b.casNext(n, f)) |
1286 |
> |
Comparable<? super K> ck = comparable(key); |
1287 |
> |
if (!n.appendMarker(f) || !b.casNext(n, f)) |
1288 |
|
findNode(ck); // Retry via findNode |
1289 |
|
else { |
1290 |
|
findPredecessor(ck); // Clean index |
1291 |
< |
if (head.right == null) |
1291 |
> |
if (head.right == null) |
1292 |
|
tryReduceLevel(); |
1293 |
|
} |
1294 |
|
if (keyOnly) |
1304 |
|
* last valid node. Needed by doRemoveLast. It is possible that |
1305 |
|
* all successors of returned node will have been deleted upon |
1306 |
|
* return, in which case this method can be retried. |
1307 |
< |
* @return likely predecessor of last node. |
1307 |
> |
* @return likely predecessor of last node. |
1308 |
|
*/ |
1309 |
|
private Node<K,V> findPredecessorOfLast() { |
1310 |
|
for (;;) { |
1322 |
|
continue; |
1323 |
|
} |
1324 |
|
} |
1325 |
< |
if ((d = q.down) != null) |
1325 |
> |
if ((d = q.down) != null) |
1326 |
|
q = d; |
1327 |
< |
else |
1327 |
> |
else |
1328 |
|
return q.node; |
1329 |
|
} |
1330 |
|
} |
1331 |
|
} |
1332 |
|
|
1333 |
|
/** |
1334 |
< |
* Remove last entry; return key or null if empty. |
1334 |
> |
* Remove last entry; return key or null if empty. |
1335 |
|
*/ |
1336 |
|
K pollLastKey() { |
1337 |
|
return (K)doRemoveLast(true); |
1352 |
|
* @return nearest node fitting relation, or null if no such |
1353 |
|
*/ |
1354 |
|
Node<K,V> findNear(K kkey, int rel) { |
1355 |
< |
Comparable<K> key = comparable(kkey); |
1355 |
> |
Comparable<? super K> key = comparable(kkey); |
1356 |
|
for (;;) { |
1357 |
|
Node<K,V> b = findPredecessor(key); |
1358 |
|
Node<K,V> n = b.next; |
1359 |
|
for (;;) { |
1360 |
< |
if (n == null) |
1360 |
> |
if (n == null) |
1361 |
|
return ((rel & LT) == 0 || b.isBaseHeader())? null : b; |
1362 |
|
Node<K,V> f = n.next; |
1363 |
|
if (n != b.next) // inconsistent read |
1502 |
|
|
1503 |
|
/** |
1504 |
|
* Constructs a new empty map, sorted according to the keys' natural |
1505 |
< |
* order. |
1505 |
> |
* order. |
1506 |
|
*/ |
1507 |
|
public ConcurrentSkipListMap() { |
1508 |
|
this.comparator = null; |
1523 |
|
|
1524 |
|
/** |
1525 |
|
* Constructs a new map containing the same mappings as the given map, |
1526 |
< |
* sorted according to the keys' <i>natural order</i>. |
1526 |
> |
* sorted according to the keys' <i>natural order</i>. |
1527 |
|
* |
1528 |
|
* @param m the map whose mappings are to be placed in this map. |
1529 |
|
* @throws ClassCastException if the keys in m are not Comparable, or |
1538 |
|
|
1539 |
|
/** |
1540 |
|
* Constructs a new map containing the same mappings as the given |
1541 |
< |
* <tt>SortedMap</tt>, sorted according to the same ordering. |
1541 |
> |
* <tt>SortedMap</tt>, sorted according to the same ordering. |
1542 |
|
* @param m the sorted map whose mappings are to be placed in this |
1543 |
|
* map, and whose comparator is to be used to sort this map. |
1544 |
|
* @throws NullPointerException if the specified sorted map is |
1586 |
|
ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>(); |
1587 |
|
|
1588 |
|
// initialize |
1589 |
< |
for (int i = 0; i <= h.level; ++i) |
1589 |
> |
for (int i = 0; i <= h.level; ++i) |
1590 |
|
preds.add(null); |
1591 |
|
Index<K,V> q = h; |
1592 |
|
for (int i = h.level; i > 0; --i) { |
1594 |
|
q = q.down; |
1595 |
|
} |
1596 |
|
|
1597 |
< |
Iterator<? extends Map.Entry<? extends K, ? extends V>> it = |
1597 |
> |
Iterator<? extends Map.Entry<? extends K, ? extends V>> it = |
1598 |
|
map.entrySet().iterator(); |
1599 |
|
while (it.hasNext()) { |
1600 |
|
Map.Entry<? extends K, ? extends V> e = it.next(); |
1611 |
|
Index<K,V> idx = null; |
1612 |
|
for (int i = 1; i <= j; ++i) { |
1613 |
|
idx = new Index<K,V>(z, idx, null); |
1614 |
< |
if (i > h.level) |
1614 |
> |
if (i > h.level) |
1615 |
|
h = new HeadIndex<K,V>(h.node, h, idx, i); |
1616 |
|
|
1617 |
|
if (i < preds.size()) { |
1631 |
|
* Save the state of the <tt>Map</tt> instance to a stream. |
1632 |
|
* |
1633 |
|
* @serialData The key (Object) and value (Object) for each |
1634 |
< |
* key-value mapping represented by the Map, followed by |
1634 |
> |
* key-value mapping represented by the Map, followed by |
1635 |
|
* <tt>null</tt>. The key-value mappings are emitted in key-order |
1636 |
|
* (as determined by the Comparator, or by the keys' natural |
1637 |
|
* ordering if no Comparator). |
1662 |
|
// Reset transients |
1663 |
|
initialize(); |
1664 |
|
|
1665 |
< |
/* |
1665 |
> |
/* |
1666 |
|
* This is nearly identical to buildFromSorted, but is |
1667 |
|
* distinct because readObject calls can't be nicely adapted |
1668 |
|
* as the kind of iterator needed by buildFromSorted. (They |
1673 |
|
HeadIndex<K,V> h = head; |
1674 |
|
Node<K,V> basepred = h.node; |
1675 |
|
ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>(); |
1676 |
< |
for (int i = 0; i <= h.level; ++i) |
1676 |
> |
for (int i = 0; i <= h.level; ++i) |
1677 |
|
preds.add(null); |
1678 |
|
Index<K,V> q = h; |
1679 |
|
for (int i = h.level; i > 0; --i) { |
1686 |
|
if (k == null) |
1687 |
|
break; |
1688 |
|
Object v = s.readObject(); |
1689 |
< |
if (v == null) |
1689 |
> |
if (v == null) |
1690 |
|
throw new NullPointerException(); |
1691 |
|
K key = (K) k; |
1692 |
|
V val = (V) v; |
1699 |
|
Index<K,V> idx = null; |
1700 |
|
for (int i = 1; i <= j; ++i) { |
1701 |
|
idx = new Index<K,V>(z, idx, null); |
1702 |
< |
if (i > h.level) |
1702 |
> |
if (i > h.level) |
1703 |
|
h = new HeadIndex<K,V>(h.node, h, idx, i); |
1704 |
|
|
1705 |
|
if (i < preds.size()) { |
1731 |
|
|
1732 |
|
/** |
1733 |
|
* Returns the value to which this map maps the specified key. Returns |
1734 |
< |
* <tt>null</tt> if the map contains no mapping for this key. |
1734 |
> |
* <tt>null</tt> if the map contains no mapping for this key. |
1735 |
|
* |
1736 |
|
* @param key key whose associated value is to be returned. |
1737 |
|
* @return the value to which this map maps the specified key, or |
1753 |
|
* @param value value to be associated with the specified key. |
1754 |
|
* |
1755 |
|
* @return the previous value associated with specified key, or <tt>null</tt> |
1756 |
< |
* if there was no mapping for key. |
1756 |
> |
* if there was no mapping for key. |
1757 |
|
* @throws ClassCastException if the key cannot be compared with the keys |
1758 |
|
* currently in the map. |
1759 |
|
* @throws NullPointerException if the key or value are <tt>null</tt>. |
1760 |
|
*/ |
1761 |
|
public V put(K key, V value) { |
1762 |
< |
if (value == null) |
1762 |
> |
if (value == null) |
1763 |
|
throw new NullPointerException(); |
1764 |
|
return doPut(key, value, false); |
1765 |
|
} |
1769 |
|
* |
1770 |
|
* @param key key for which mapping should be removed |
1771 |
|
* @return the previous value associated with specified key, or <tt>null</tt> |
1772 |
< |
* if there was no mapping for key. |
1772 |
> |
* if there was no mapping for key. |
1773 |
|
* |
1774 |
|
* @throws ClassCastException if the key cannot be compared with the keys |
1775 |
|
* currently in the map. |
1788 |
|
* @return <tt>true</tt> if a mapping to <tt>value</tt> exists; |
1789 |
|
* <tt>false</tt> otherwise. |
1790 |
|
* @throws NullPointerException if the value is <tt>null</tt>. |
1791 |
< |
*/ |
1791 |
> |
*/ |
1792 |
|
public boolean containsValue(Object value) { |
1793 |
< |
if (value == null) |
1793 |
> |
if (value == null) |
1794 |
|
throw new NullPointerException(); |
1795 |
|
for (Node<K,V> n = findFirst(); n != null; n = n.next) { |
1796 |
|
V v = n.getValidValue(); |
2001 |
|
return false; |
2002 |
|
Map<K,V> t = (Map<K,V>) o; |
2003 |
|
try { |
2004 |
< |
return (containsAllMappings(this, t) && |
2004 |
> |
return (containsAllMappings(this, t) && |
2005 |
|
containsAllMappings(t, this)); |
2006 |
|
} catch(ClassCastException unused) { |
2007 |
|
return false; |
2019 |
|
Entry<K,V> e = it.next(); |
2020 |
|
Object k = e.getKey(); |
2021 |
|
Object v = e.getValue(); |
2022 |
< |
if (k == null || v == null || !v.equals(a.get(k))) |
2022 |
> |
if (k == null || v == null || !v.equals(a.get(k))) |
2023 |
|
return false; |
2024 |
|
} |
2025 |
|
return true; |
2032 |
|
* with a value, associate it with the given value. |
2033 |
|
* This is equivalent to |
2034 |
|
* <pre> |
2035 |
< |
* if (!map.containsKey(key)) |
2035 |
> |
* if (!map.containsKey(key)) |
2036 |
|
* return map.put(key, value); |
2037 |
|
* else |
2038 |
|
* return map.get(key); |
2041 |
|
* @param key key with which the specified value is to be associated. |
2042 |
|
* @param value value to be associated with the specified key. |
2043 |
|
* @return the previous value associated with specified key, or <tt>null</tt> |
2044 |
< |
* if there was no mapping for key. |
2044 |
> |
* if there was no mapping for key. |
2045 |
|
* |
2046 |
|
* @throws ClassCastException if the key cannot be compared with the keys |
2047 |
|
* currently in the map. |
2048 |
|
* @throws NullPointerException if the key or value are <tt>null</tt>. |
2049 |
|
*/ |
2050 |
|
public V putIfAbsent(K key, V value) { |
2051 |
< |
if (value == null) |
2051 |
> |
if (value == null) |
2052 |
|
throw new NullPointerException(); |
2053 |
|
return doPut(key, value, true); |
2054 |
|
} |
2056 |
|
/** |
2057 |
|
* Remove entry for key only if currently mapped to given value. |
2058 |
|
* Acts as |
2059 |
< |
* <pre> |
2059 |
> |
* <pre> |
2060 |
|
* if ((map.containsKey(key) && map.get(key).equals(value)) { |
2061 |
|
* map.remove(key); |
2062 |
|
* return true; |
2071 |
|
* @throws NullPointerException if the key or value are <tt>null</tt>. |
2072 |
|
*/ |
2073 |
|
public boolean remove(Object key, Object value) { |
2074 |
< |
if (value == null) |
2074 |
> |
if (value == null) |
2075 |
|
throw new NullPointerException(); |
2076 |
|
return doRemove(key, value) != null; |
2077 |
|
} |
2079 |
|
/** |
2080 |
|
* Replace entry for key only if currently mapped to given value. |
2081 |
|
* Acts as |
2082 |
< |
* <pre> |
2082 |
> |
* <pre> |
2083 |
|
* if ((map.containsKey(key) && map.get(key).equals(oldValue)) { |
2084 |
|
* map.put(key, newValue); |
2085 |
|
* return true; |
2096 |
|
* <tt>null</tt>. |
2097 |
|
*/ |
2098 |
|
public boolean replace(K key, V oldValue, V newValue) { |
2099 |
< |
if (oldValue == null || newValue == null) |
2099 |
> |
if (oldValue == null || newValue == null) |
2100 |
|
throw new NullPointerException(); |
2101 |
< |
Comparable<K> k = comparable(key); |
2101 |
> |
Comparable<? super K> k = comparable(key); |
2102 |
|
for (;;) { |
2103 |
|
Node<K,V> n = findNode(k); |
2104 |
|
if (n == null) |
2116 |
|
/** |
2117 |
|
* Replace entry for key only if currently mapped to some value. |
2118 |
|
* Acts as |
2119 |
< |
* <pre> |
2119 |
> |
* <pre> |
2120 |
|
* if ((map.containsKey(key)) { |
2121 |
|
* return map.put(key, value); |
2122 |
|
* } else return null; |
2125 |
|
* @param key key with which the specified value is associated. |
2126 |
|
* @param value value to be associated with the specified key. |
2127 |
|
* @return the previous value associated with specified key, or <tt>null</tt> |
2128 |
< |
* if there was no mapping for key. |
2128 |
> |
* if there was no mapping for key. |
2129 |
|
* @throws ClassCastException if the key cannot be compared with the keys |
2130 |
|
* currently in the map. |
2131 |
|
* @throws NullPointerException if the key or value are <tt>null</tt>. |
2132 |
|
*/ |
2133 |
|
public V replace(K key, V value) { |
2134 |
< |
if (value == null) |
2134 |
> |
if (value == null) |
2135 |
|
throw new NullPointerException(); |
2136 |
< |
Comparable<K> k = comparable(key); |
2136 |
> |
Comparable<? super K> k = comparable(key); |
2137 |
|
for (;;) { |
2138 |
|
Node<K,V> n = findNode(k); |
2139 |
|
if (n == null) |
2163 |
|
* @return the first (lowest) key currently in this map. |
2164 |
|
* @throws NoSuchElementException Map is empty. |
2165 |
|
*/ |
2166 |
< |
public K firstKey() { |
2166 |
> |
public K firstKey() { |
2167 |
|
Node<K,V> n = findFirst(); |
2168 |
|
if (n == null) |
2169 |
|
throw new NoSuchElementException(); |
2311 |
|
* greater than or equal to the given key, or <tt>null</tt> if |
2312 |
|
* there is no such entry. The returned entry does <em>not</em> |
2313 |
|
* support the <tt>Entry.setValue</tt> method. |
2314 |
< |
* |
2314 |
> |
* |
2315 |
|
* @param key the key. |
2316 |
|
* @return an Entry associated with ceiling of given key, or |
2317 |
|
* <tt>null</tt> if there is no such Entry. |
2326 |
|
/** |
2327 |
|
* Returns least key greater than or equal to the given key, or |
2328 |
|
* <tt>null</tt> if there is no such key. |
2329 |
< |
* |
2329 |
> |
* |
2330 |
|
* @param key the key. |
2331 |
|
* @return the ceiling key, or <tt>null</tt> |
2332 |
|
* if there is no such key. |
2344 |
|
* key strictly less than the given key, or <tt>null</tt> if there is no |
2345 |
|
* such entry. The returned entry does <em>not</em> support |
2346 |
|
* the <tt>Entry.setValue</tt> method. |
2347 |
< |
* |
2347 |
> |
* |
2348 |
|
* @param key the key. |
2349 |
|
* @return an Entry with greatest key less than the given |
2350 |
|
* key, or <tt>null</tt> if there is no such Entry. |
2359 |
|
/** |
2360 |
|
* Returns the greatest key strictly less than the given key, or |
2361 |
|
* <tt>null</tt> if there is no such key. |
2362 |
< |
* |
2362 |
> |
* |
2363 |
|
* @param key the key. |
2364 |
|
* @return the greatest key less than the given |
2365 |
|
* key, or <tt>null</tt> if there is no such key. |
2377 |
|
* less than or equal to the given key, or <tt>null</tt> if there |
2378 |
|
* is no such entry. The returned entry does <em>not</em> support |
2379 |
|
* the <tt>Entry.setValue</tt> method. |
2380 |
< |
* |
2380 |
> |
* |
2381 |
|
* @param key the key. |
2382 |
|
* @return an Entry associated with floor of given key, or <tt>null</tt> |
2383 |
|
* if there is no such Entry. |
2393 |
|
* Returns the greatest key |
2394 |
|
* less than or equal to the given key, or <tt>null</tt> if there |
2395 |
|
* is no such key. |
2396 |
< |
* |
2396 |
> |
* |
2397 |
|
* @param key the key. |
2398 |
|
* @return the floor of given key, or <tt>null</tt> if there is no |
2399 |
|
* such key. |
2411 |
|
* strictly greater than the given key, or <tt>null</tt> if there |
2412 |
|
* is no such entry. The returned entry does <em>not</em> support |
2413 |
|
* the <tt>Entry.setValue</tt> method. |
2414 |
< |
* |
2414 |
> |
* |
2415 |
|
* @param key the key. |
2416 |
|
* @return an Entry with least key greater than the given key, or |
2417 |
|
* <tt>null</tt> if there is no such Entry. |
2426 |
|
/** |
2427 |
|
* Returns the least key strictly greater than the given key, or |
2428 |
|
* <tt>null</tt> if there is no such key. |
2429 |
< |
* |
2429 |
> |
* |
2430 |
|
* @param key the key. |
2431 |
|
* @return the least key greater than the given key, or |
2432 |
|
* <tt>null</tt> if there is no such key. |
2444 |
|
* key in this map, or <tt>null</tt> if the map is empty. |
2445 |
|
* The returned entry does <em>not</em> support |
2446 |
|
* the <tt>Entry.setValue</tt> method. |
2447 |
< |
* |
2448 |
< |
* @return an Entry with least key, or <tt>null</tt> |
2447 |
> |
* |
2448 |
> |
* @return an Entry with least key, or <tt>null</tt> |
2449 |
|
* if the map is empty. |
2450 |
|
*/ |
2451 |
|
public Map.Entry<K,V> firstEntry() { |
2452 |
|
for (;;) { |
2453 |
|
Node<K,V> n = findFirst(); |
2454 |
< |
if (n == null) |
2454 |
> |
if (n == null) |
2455 |
|
return null; |
2456 |
|
AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot(); |
2457 |
|
if (e != null) |
2464 |
|
* key in this map, or <tt>null</tt> if the map is empty. |
2465 |
|
* The returned entry does <em>not</em> support |
2466 |
|
* the <tt>Entry.setValue</tt> method. |
2467 |
< |
* |
2467 |
> |
* |
2468 |
|
* @return an Entry with greatest key, or <tt>null</tt> |
2469 |
|
* if the map is empty. |
2470 |
|
*/ |
2471 |
|
public Map.Entry<K,V> lastEntry() { |
2472 |
|
for (;;) { |
2473 |
|
Node<K,V> n = findLast(); |
2474 |
< |
if (n == null) |
2474 |
> |
if (n == null) |
2475 |
|
return null; |
2476 |
|
AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot(); |
2477 |
|
if (e != null) |
2484 |
|
* the least key in this map, or <tt>null</tt> if the map is empty. |
2485 |
|
* The returned entry does <em>not</em> support |
2486 |
|
* the <tt>Entry.setValue</tt> method. |
2487 |
< |
* |
2487 |
> |
* |
2488 |
|
* @return the removed first entry of this map, or <tt>null</tt> |
2489 |
|
* if the map is empty. |
2490 |
|
*/ |
2497 |
|
* the greatest key in this map, or <tt>null</tt> if the map is empty. |
2498 |
|
* The returned entry does <em>not</em> support |
2499 |
|
* the <tt>Entry.setValue</tt> method. |
2500 |
< |
* |
2500 |
> |
* |
2501 |
|
* @return the removed last entry of this map, or <tt>null</tt> |
2502 |
|
* if the map is empty. |
2503 |
|
*/ |
2510 |
|
|
2511 |
|
/** |
2512 |
|
* Base of ten kinds of iterator classes: |
2513 |
< |
* ascending: {map, submap} X {key, value, entry} |
2514 |
< |
* descending: {map, submap} X {key, entry} |
2513 |
> |
* ascending: {map, submap} X {key, value, entry} |
2514 |
> |
* descending: {map, submap} X {key, entry} |
2515 |
|
*/ |
2516 |
|
abstract class Iter { |
2517 |
|
/** the last node returned by next() */ |
2523 |
|
|
2524 |
|
Iter() {} |
2525 |
|
|
2526 |
< |
public final boolean hasNext() { |
2527 |
< |
return next != null; |
2526 |
> |
public final boolean hasNext() { |
2527 |
> |
return next != null; |
2528 |
|
} |
2529 |
|
|
2530 |
|
/** initialize ascending iterator for entire range */ |
2539 |
|
} |
2540 |
|
} |
2541 |
|
|
2542 |
< |
/** |
2542 |
> |
/** |
2543 |
|
* initialize ascending iterator starting at given least key, |
2544 |
|
* or first node if least is <tt>null</tt>, but not greater or |
2545 |
|
* equal to fence, or end if fence is <tt>null</tt>. |
2546 |
|
*/ |
2547 |
< |
final void initAscending(K least, K fence) { |
2547 |
> |
final void initAscending(K least, K fence) { |
2548 |
|
for (;;) { |
2549 |
|
next = findCeiling(least); |
2550 |
|
if (next == null) |
2606 |
|
} |
2607 |
|
} |
2608 |
|
|
2609 |
< |
/** |
2609 |
> |
/** |
2610 |
|
* initialize descending iterator starting at key less |
2611 |
|
* than or equal to given fence key, or |
2612 |
|
* last node if fence is <tt>null</tt>, but not less than |
2613 |
|
* least, or beginning if lest is <tt>null</tt>. |
2614 |
|
*/ |
2615 |
< |
final void initDescending(K least, K fence) { |
2615 |
> |
final void initDescending(K least, K fence) { |
2616 |
|
for (;;) { |
2617 |
|
next = findLower(fence); |
2618 |
|
if (next == null) |
2680 |
|
ValueIterator() { |
2681 |
|
initAscending(); |
2682 |
|
} |
2683 |
< |
public V next() { |
2683 |
> |
public V next() { |
2684 |
|
Object v = nextValue; |
2685 |
|
ascend(); |
2686 |
|
return (V)v; |
2691 |
|
KeyIterator() { |
2692 |
|
initAscending(); |
2693 |
|
} |
2694 |
< |
public K next() { |
2694 |
> |
public K next() { |
2695 |
|
Node<K,V> n = next; |
2696 |
|
ascend(); |
2697 |
|
return n.key; |
2705 |
|
this.fence = fence; |
2706 |
|
} |
2707 |
|
|
2708 |
< |
public V next() { |
2708 |
> |
public V next() { |
2709 |
|
Object v = nextValue; |
2710 |
|
ascend(fence); |
2711 |
|
return (V)v; |
2719 |
|
this.fence = fence; |
2720 |
|
} |
2721 |
|
|
2722 |
< |
public K next() { |
2722 |
> |
public K next() { |
2723 |
|
Node<K,V> n = next; |
2724 |
|
ascend(fence); |
2725 |
|
return n.key; |
2730 |
|
DescendingKeyIterator() { |
2731 |
|
initDescending(); |
2732 |
|
} |
2733 |
< |
public K next() { |
2733 |
> |
public K next() { |
2734 |
|
Node<K,V> n = next; |
2735 |
|
descend(); |
2736 |
|
return n.key; |
2744 |
|
this.least = least; |
2745 |
|
} |
2746 |
|
|
2747 |
< |
public K next() { |
2747 |
> |
public K next() { |
2748 |
|
Node<K,V> n = next; |
2749 |
|
descend(least); |
2750 |
|
return n.key; |
2760 |
|
/** Cache of last value returned */ |
2761 |
|
Object lastValue; |
2762 |
|
|
2763 |
< |
EntryIter() { |
2763 |
> |
EntryIter() { |
2764 |
|
} |
2765 |
|
|
2766 |
|
public K getKey() { |
2807 |
|
} |
2808 |
|
} |
2809 |
|
|
2810 |
< |
final class EntryIterator extends EntryIter |
2810 |
> |
final class EntryIterator extends EntryIter |
2811 |
|
implements Iterator<Map.Entry<K,V>> { |
2812 |
< |
EntryIterator() { |
2813 |
< |
initAscending(); |
2812 |
> |
EntryIterator() { |
2813 |
> |
initAscending(); |
2814 |
|
} |
2815 |
< |
public Map.Entry<K,V> next() { |
2815 |
> |
public Map.Entry<K,V> next() { |
2816 |
|
lastValue = nextValue; |
2817 |
|
ascend(); |
2818 |
|
return this; |
2819 |
|
} |
2820 |
|
} |
2821 |
|
|
2822 |
< |
final class SubMapEntryIterator extends EntryIter |
2822 |
> |
final class SubMapEntryIterator extends EntryIter |
2823 |
|
implements Iterator<Map.Entry<K,V>> { |
2824 |
|
final K fence; |
2825 |
|
SubMapEntryIterator(K least, K fence) { |
2827 |
|
this.fence = fence; |
2828 |
|
} |
2829 |
|
|
2830 |
< |
public Map.Entry<K,V> next() { |
2830 |
> |
public Map.Entry<K,V> next() { |
2831 |
|
lastValue = nextValue; |
2832 |
|
ascend(fence); |
2833 |
|
return this; |
2834 |
|
} |
2835 |
|
} |
2836 |
|
|
2837 |
< |
final class DescendingEntryIterator extends EntryIter |
2837 |
> |
final class DescendingEntryIterator extends EntryIter |
2838 |
|
implements Iterator<Map.Entry<K,V>> { |
2839 |
< |
DescendingEntryIterator() { |
2840 |
< |
initDescending(); |
2839 |
> |
DescendingEntryIterator() { |
2840 |
> |
initDescending(); |
2841 |
|
} |
2842 |
< |
public Map.Entry<K,V> next() { |
2842 |
> |
public Map.Entry<K,V> next() { |
2843 |
|
lastValue = nextValue; |
2844 |
|
descend(); |
2845 |
|
return this; |
2846 |
|
} |
2847 |
|
} |
2848 |
|
|
2849 |
< |
final class DescendingSubMapEntryIterator extends EntryIter |
2849 |
> |
final class DescendingSubMapEntryIterator extends EntryIter |
2850 |
|
implements Iterator<Map.Entry<K,V>> { |
2851 |
|
final K least; |
2852 |
|
DescendingSubMapEntryIterator(K least, K fence) { |
2854 |
|
this.least = least; |
2855 |
|
} |
2856 |
|
|
2857 |
< |
public Map.Entry<K,V> next() { |
2857 |
> |
public Map.Entry<K,V> next() { |
2858 |
|
lastValue = nextValue; |
2859 |
|
descend(least); |
2860 |
|
return this; |
2978 |
|
if (!(o instanceof Map.Entry)) |
2979 |
|
return false; |
2980 |
|
Map.Entry<K,V> e = (Map.Entry<K,V>)o; |
2981 |
< |
return ConcurrentSkipListMap.this.remove(e.getKey(), |
2981 |
> |
return ConcurrentSkipListMap.this.remove(e.getKey(), |
2982 |
|
e.getValue()); |
2983 |
|
} |
2984 |
|
public boolean isEmpty() { |
2993 |
|
|
2994 |
|
public Object[] toArray() { |
2995 |
|
Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(); |
2996 |
< |
for (Map.Entry e : this) |
2996 |
> |
for (Map.Entry e : this) |
2997 |
|
c.add(new AbstractMap.SimpleEntry(e.getKey(), e.getValue())); |
2998 |
|
return c.toArray(); |
2999 |
|
} |
3000 |
|
public <T> T[] toArray(T[] a) { |
3001 |
|
Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(); |
3002 |
< |
for (Map.Entry e : this) |
3002 |
> |
for (Map.Entry e : this) |
3003 |
|
c.add(new AbstractMap.SimpleEntry(e.getKey(), e.getValue())); |
3004 |
|
return c.toArray(a); |
3005 |
|
} |
3029 |
|
/** Underlying map */ |
3030 |
|
private final ConcurrentSkipListMap<K,V> m; |
3031 |
|
/** lower bound key, or null if from start */ |
3032 |
< |
private final K least; |
3032 |
> |
private final K least; |
3033 |
|
/** upper fence key, or null if to end */ |
3034 |
< |
private final K fence; |
3034 |
> |
private final K fence; |
3035 |
|
// Lazily initialized view holders |
3036 |
|
private transient Set<K> keySetView; |
3037 |
|
private transient Set<Map.Entry<K,V>> entrySetView; |
3040 |
|
private transient Set<Map.Entry<K,V>> descendingEntrySetView; |
3041 |
|
|
3042 |
|
/** |
3043 |
< |
* Creates a new submap. |
3043 |
> |
* Creates a new submap. |
3044 |
|
* @param least inclusive least value, or <tt>null</tt> if from start |
3045 |
|
* @param fence exclusive upper bound or <tt>null</tt> if to end |
3046 |
|
* @throws IllegalArgumentException if least and fence nonnull |
3047 |
|
* and least greater than fence |
3048 |
|
*/ |
3049 |
< |
ConcurrentSkipListSubMap(ConcurrentSkipListMap<K,V> map, |
3049 |
> |
ConcurrentSkipListSubMap(ConcurrentSkipListMap<K,V> map, |
3050 |
|
K least, K fence) { |
3051 |
< |
if (least != null && |
3052 |
< |
fence != null && |
3051 |
> |
if (least != null && |
3052 |
> |
fence != null && |
3053 |
|
map.compare(least, fence) > 0) |
3054 |
|
throw new IllegalArgumentException("inconsistent range"); |
3055 |
|
this.m = map; |
3076 |
|
} |
3077 |
|
|
3078 |
|
boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) { |
3079 |
< |
return (n != null && |
3080 |
< |
(fence == null || |
3079 |
> |
return (n != null && |
3080 |
> |
(fence == null || |
3081 |
|
n.key == null || // pass by markers and headers |
3082 |
|
m.compare(fence, n.key) > 0)); |
3083 |
|
} |
3136 |
|
|
3137 |
|
public int size() { |
3138 |
|
long count = 0; |
3139 |
< |
for (ConcurrentSkipListMap.Node<K,V> n = firstNode(); |
3140 |
< |
isBeforeEnd(n); |
3139 |
> |
for (ConcurrentSkipListMap.Node<K,V> n = firstNode(); |
3140 |
> |
isBeforeEnd(n); |
3141 |
|
n = n.next) { |
3142 |
|
if (n.getValidValue() != null) |
3143 |
|
++count; |
3150 |
|
} |
3151 |
|
|
3152 |
|
public boolean containsValue(Object value) { |
3153 |
< |
if (value == null) |
3153 |
> |
if (value == null) |
3154 |
|
throw new NullPointerException(); |
3155 |
< |
for (ConcurrentSkipListMap.Node<K,V> n = firstNode(); |
3156 |
< |
isBeforeEnd(n); |
3155 |
> |
for (ConcurrentSkipListMap.Node<K,V> n = firstNode(); |
3156 |
> |
isBeforeEnd(n); |
3157 |
|
n = n.next) { |
3158 |
|
V v = n.getValidValue(); |
3159 |
|
if (v != null && value.equals(v)) |
3163 |
|
} |
3164 |
|
|
3165 |
|
public void clear() { |
3166 |
< |
for (ConcurrentSkipListMap.Node<K,V> n = firstNode(); |
3167 |
< |
isBeforeEnd(n); |
3166 |
> |
for (ConcurrentSkipListMap.Node<K,V> n = firstNode(); |
3167 |
> |
isBeforeEnd(n); |
3168 |
|
n = n.next) { |
3169 |
|
if (n.getValidValue() != null) |
3170 |
|
m.remove(n.key); |
3285 |
|
m.getNear(key, m.LT|m.EQ, least, fence, true); |
3286 |
|
} |
3287 |
|
|
3288 |
< |
|
3288 |
> |
|
3289 |
|
public Map.Entry<K,V> higherEntry(K key) { |
3290 |
|
return (Map.Entry<K,V>) |
3291 |
|
m.getNear(key, m.GT, least, fence, false); |
3299 |
|
public Map.Entry<K,V> firstEntry() { |
3300 |
|
for (;;) { |
3301 |
|
ConcurrentSkipListMap.Node<K,V> n = firstNode(); |
3302 |
< |
if (!isBeforeEnd(n)) |
3302 |
> |
if (!isBeforeEnd(n)) |
3303 |
|
return null; |
3304 |
|
Map.Entry<K,V> e = n.createSnapshot(); |
3305 |
|
if (e != null) |
3441 |
|
} |
3442 |
|
public Object[] toArray() { |
3443 |
|
Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(); |
3444 |
< |
for (Map.Entry e : this) |
3444 |
> |
for (Map.Entry e : this) |
3445 |
|
c.add(new AbstractMap.SimpleEntry(e.getKey(), e.getValue())); |
3446 |
|
return c.toArray(); |
3447 |
|
} |
3448 |
|
public <T> T[] toArray(T[] a) { |
3449 |
|
Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(); |
3450 |
< |
for (Map.Entry e : this) |
3450 |
> |
for (Map.Entry e : this) |
3451 |
|
c.add(new AbstractMap.SimpleEntry(e.getKey(), e.getValue())); |
3452 |
|
return c.toArray(a); |
3453 |
|
} |