author | mchung |
Tue, 06 Nov 2018 10:01:16 -0800 | |
changeset 52427 | 3c6aa484536c |
parent 49433 | b6671a111395 |
child 57956 | e0b8b019d2f5 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
49433
b6671a111395
8199465: {@docRoot} references need to be updated to reflect new module/package structure
jjg
parents:
47423
diff
changeset
|
2 |
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package java.util; |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
27 |
|
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
28 |
import java.lang.reflect.Array; |
18280
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
29 |
import java.util.function.BiConsumer; |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
30 |
import java.util.function.BiFunction; |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
31 |
import java.util.function.Consumer; |
52427
3c6aa484536c
8211122: Reduce the number of internal classes made accessible to jdk.unsupported
mchung
parents:
49433
diff
changeset
|
32 |
import jdk.internal.access.SharedSecrets; |
2 | 33 |
|
34 |
/** |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
35 |
* This class implements the {@code Map} interface with a hash table, using |
2 | 36 |
* reference-equality in place of object-equality when comparing keys (and |
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
37 |
* values). In other words, in an {@code IdentityHashMap}, two keys |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
38 |
* {@code k1} and {@code k2} are considered equal if and only if |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
39 |
* {@code (k1==k2)}. (In normal {@code Map} implementations (like |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
40 |
* {@code HashMap}) two keys {@code k1} and {@code k2} are considered equal |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
41 |
* if and only if {@code (k1==null ? k2==null : k1.equals(k2))}.) |
2 | 42 |
* |
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
43 |
* <p><b>This class is <i>not</i> a general-purpose {@code Map} |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
44 |
* implementation! While this class implements the {@code Map} interface, it |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
45 |
* intentionally violates {@code Map's} general contract, which mandates the |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
46 |
* use of the {@code equals} method when comparing objects. This class is |
2 | 47 |
* designed for use only in the rare cases wherein reference-equality |
48 |
* semantics are required.</b> |
|
49 |
* |
|
50 |
* <p>A typical use of this class is <i>topology-preserving object graph |
|
51 |
* transformations</i>, such as serialization or deep-copying. To perform such |
|
52 |
* a transformation, a program must maintain a "node table" that keeps track |
|
53 |
* of all the object references that have already been processed. The node |
|
54 |
* table must not equate distinct objects even if they happen to be equal. |
|
55 |
* Another typical use of this class is to maintain <i>proxy objects</i>. For |
|
56 |
* example, a debugging facility might wish to maintain a proxy object for |
|
57 |
* each object in the program being debugged. |
|
58 |
* |
|
59 |
* <p>This class provides all of the optional map operations, and permits |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
60 |
* {@code null} values and the {@code null} key. This class makes no |
2 | 61 |
* guarantees as to the order of the map; in particular, it does not guarantee |
62 |
* that the order will remain constant over time. |
|
63 |
* |
|
64 |
* <p>This class provides constant-time performance for the basic |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
65 |
* operations ({@code get} and {@code put}), assuming the system |
2 | 66 |
* identity hash function ({@link System#identityHashCode(Object)}) |
67 |
* disperses elements properly among the buckets. |
|
68 |
* |
|
69 |
* <p>This class has one tuning parameter (which affects performance but not |
|
70 |
* semantics): <i>expected maximum size</i>. This parameter is the maximum |
|
71 |
* number of key-value mappings that the map is expected to hold. Internally, |
|
72 |
* this parameter is used to determine the number of buckets initially |
|
73 |
* comprising the hash table. The precise relationship between the expected |
|
74 |
* maximum size and the number of buckets is unspecified. |
|
75 |
* |
|
76 |
* <p>If the size of the map (the number of key-value mappings) sufficiently |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
77 |
* exceeds the expected maximum size, the number of buckets is increased. |
2 | 78 |
* Increasing the number of buckets ("rehashing") may be fairly expensive, so |
79 |
* it pays to create identity hash maps with a sufficiently large expected |
|
80 |
* maximum size. On the other hand, iteration over collection views requires |
|
81 |
* time proportional to the number of buckets in the hash table, so it |
|
82 |
* pays not to set the expected maximum size too high if you are especially |
|
83 |
* concerned with iteration performance or memory usage. |
|
84 |
* |
|
85 |
* <p><strong>Note that this implementation is not synchronized.</strong> |
|
86 |
* If multiple threads access an identity hash map concurrently, and at |
|
87 |
* least one of the threads modifies the map structurally, it <i>must</i> |
|
88 |
* be synchronized externally. (A structural modification is any operation |
|
89 |
* that adds or deletes one or more mappings; merely changing the value |
|
90 |
* associated with a key that an instance already contains is not a |
|
91 |
* structural modification.) This is typically accomplished by |
|
92 |
* synchronizing on some object that naturally encapsulates the map. |
|
93 |
* |
|
94 |
* If no such object exists, the map should be "wrapped" using the |
|
95 |
* {@link Collections#synchronizedMap Collections.synchronizedMap} |
|
96 |
* method. This is best done at creation time, to prevent accidental |
|
97 |
* unsynchronized access to the map:<pre> |
|
98 |
* Map m = Collections.synchronizedMap(new IdentityHashMap(...));</pre> |
|
99 |
* |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
100 |
* <p>The iterators returned by the {@code iterator} method of the |
2 | 101 |
* collections returned by all of this class's "collection view |
102 |
* methods" are <i>fail-fast</i>: if the map is structurally modified |
|
103 |
* at any time after the iterator is created, in any way except |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
104 |
* through the iterator's own {@code remove} method, the iterator |
2 | 105 |
* will throw a {@link ConcurrentModificationException}. Thus, in the |
106 |
* face of concurrent modification, the iterator fails quickly and |
|
107 |
* cleanly, rather than risking arbitrary, non-deterministic behavior |
|
108 |
* at an undetermined time in the future. |
|
109 |
* |
|
110 |
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed |
|
111 |
* as it is, generally speaking, impossible to make any hard guarantees in the |
|
112 |
* presence of unsynchronized concurrent modification. Fail-fast iterators |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
113 |
* throw {@code ConcurrentModificationException} on a best-effort basis. |
2 | 114 |
* Therefore, it would be wrong to write a program that depended on this |
115 |
* exception for its correctness: <i>fail-fast iterators should be used only |
|
116 |
* to detect bugs.</i> |
|
117 |
* |
|
118 |
* <p>Implementation note: This is a simple <i>linear-probe</i> hash table, |
|
119 |
* as described for example in texts by Sedgewick and Knuth. The array |
|
120 |
* alternates holding keys and values. (This has better locality for large |
|
121 |
* tables than does using separate arrays.) For many JRE implementations |
|
122 |
* and operation mixes, this class will yield better performance than |
|
123 |
* {@link HashMap} (which uses <i>chaining</i> rather than linear-probing). |
|
124 |
* |
|
125 |
* <p>This class is a member of the |
|
49433
b6671a111395
8199465: {@docRoot} references need to be updated to reflect new module/package structure
jjg
parents:
47423
diff
changeset
|
126 |
* <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework"> |
2 | 127 |
* Java Collections Framework</a>. |
128 |
* |
|
129 |
* @see System#identityHashCode(Object) |
|
130 |
* @see Object#hashCode() |
|
131 |
* @see Collection |
|
132 |
* @see Map |
|
133 |
* @see HashMap |
|
134 |
* @see TreeMap |
|
135 |
* @author Doug Lea and Josh Bloch |
|
136 |
* @since 1.4 |
|
137 |
*/ |
|
138 |
||
139 |
public class IdentityHashMap<K,V> |
|
140 |
extends AbstractMap<K,V> |
|
141 |
implements Map<K,V>, java.io.Serializable, Cloneable |
|
142 |
{ |
|
143 |
/** |
|
144 |
* The initial capacity used by the no-args constructor. |
|
145 |
* MUST be a power of two. The value 32 corresponds to the |
|
146 |
* (specified) expected maximum size of 21, given a load factor |
|
147 |
* of 2/3. |
|
148 |
*/ |
|
149 |
private static final int DEFAULT_CAPACITY = 32; |
|
150 |
||
151 |
/** |
|
152 |
* The minimum capacity, used if a lower value is implicitly specified |
|
153 |
* by either of the constructors with arguments. The value 4 corresponds |
|
154 |
* to an expected maximum size of 2, given a load factor of 2/3. |
|
155 |
* MUST be a power of two. |
|
156 |
*/ |
|
157 |
private static final int MINIMUM_CAPACITY = 4; |
|
158 |
||
159 |
/** |
|
160 |
* The maximum capacity, used if a higher value is implicitly specified |
|
161 |
* by either of the constructors with arguments. |
|
162 |
* MUST be a power of two <= 1<<29. |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
163 |
* |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
164 |
* In fact, the map can hold no more than MAXIMUM_CAPACITY-1 items |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
165 |
* because it has to have at least one slot with the key == null |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
166 |
* in order to avoid infinite loops in get(), put(), remove() |
2 | 167 |
*/ |
168 |
private static final int MAXIMUM_CAPACITY = 1 << 29; |
|
169 |
||
170 |
/** |
|
171 |
* The table, resized as necessary. Length MUST always be a power of two. |
|
172 |
*/ |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
173 |
transient Object[] table; // non-private to simplify nested class access |
2 | 174 |
|
175 |
/** |
|
176 |
* The number of key-value mappings contained in this identity hash map. |
|
177 |
* |
|
178 |
* @serial |
|
179 |
*/ |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
180 |
int size; |
2 | 181 |
|
182 |
/** |
|
183 |
* The number of modifications, to support fast-fail iterators |
|
184 |
*/ |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
185 |
transient int modCount; |
2 | 186 |
|
187 |
/** |
|
188 |
* Value representing null keys inside tables. |
|
189 |
*/ |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
190 |
static final Object NULL_KEY = new Object(); |
2 | 191 |
|
192 |
/** |
|
193 |
* Use NULL_KEY for key if it is null. |
|
194 |
*/ |
|
195 |
private static Object maskNull(Object key) { |
|
196 |
return (key == null ? NULL_KEY : key); |
|
197 |
} |
|
198 |
||
199 |
/** |
|
200 |
* Returns internal representation of null key back to caller as null. |
|
201 |
*/ |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
202 |
static final Object unmaskNull(Object key) { |
2 | 203 |
return (key == NULL_KEY ? null : key); |
204 |
} |
|
205 |
||
206 |
/** |
|
207 |
* Constructs a new, empty identity hash map with a default expected |
|
208 |
* maximum size (21). |
|
209 |
*/ |
|
210 |
public IdentityHashMap() { |
|
211 |
init(DEFAULT_CAPACITY); |
|
212 |
} |
|
213 |
||
214 |
/** |
|
215 |
* Constructs a new, empty map with the specified expected maximum size. |
|
216 |
* Putting more than the expected number of key-value mappings into |
|
217 |
* the map may cause the internal data structure to grow, which may be |
|
218 |
* somewhat time-consuming. |
|
219 |
* |
|
220 |
* @param expectedMaxSize the expected maximum size of the map |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
221 |
* @throws IllegalArgumentException if {@code expectedMaxSize} is negative |
2 | 222 |
*/ |
223 |
public IdentityHashMap(int expectedMaxSize) { |
|
224 |
if (expectedMaxSize < 0) |
|
225 |
throw new IllegalArgumentException("expectedMaxSize is negative: " |
|
226 |
+ expectedMaxSize); |
|
227 |
init(capacity(expectedMaxSize)); |
|
228 |
} |
|
229 |
||
230 |
/** |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
231 |
* Returns the appropriate capacity for the given expected maximum size. |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
232 |
* Returns the smallest power of two between MINIMUM_CAPACITY and |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
233 |
* MAXIMUM_CAPACITY, inclusive, that is greater than (3 * |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
234 |
* expectedMaxSize)/2, if such a number exists. Otherwise returns |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
235 |
* MAXIMUM_CAPACITY. |
2 | 236 |
*/ |
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
237 |
private static int capacity(int expectedMaxSize) { |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
238 |
// assert expectedMaxSize >= 0; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
239 |
return |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
240 |
(expectedMaxSize > MAXIMUM_CAPACITY / 3) ? MAXIMUM_CAPACITY : |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
241 |
(expectedMaxSize <= 2 * MINIMUM_CAPACITY / 3) ? MINIMUM_CAPACITY : |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
242 |
Integer.highestOneBit(expectedMaxSize + (expectedMaxSize << 1)); |
2 | 243 |
} |
244 |
||
245 |
/** |
|
246 |
* Initializes object to be an empty map with the specified initial |
|
247 |
* capacity, which is assumed to be a power of two between |
|
248 |
* MINIMUM_CAPACITY and MAXIMUM_CAPACITY inclusive. |
|
249 |
*/ |
|
250 |
private void init(int initCapacity) { |
|
251 |
// assert (initCapacity & -initCapacity) == initCapacity; // power of 2 |
|
252 |
// assert initCapacity >= MINIMUM_CAPACITY; |
|
253 |
// assert initCapacity <= MAXIMUM_CAPACITY; |
|
254 |
||
255 |
table = new Object[2 * initCapacity]; |
|
256 |
} |
|
257 |
||
258 |
/** |
|
259 |
* Constructs a new identity hash map containing the keys-value mappings |
|
260 |
* in the specified map. |
|
261 |
* |
|
262 |
* @param m the map whose mappings are to be placed into this map |
|
263 |
* @throws NullPointerException if the specified map is null |
|
264 |
*/ |
|
265 |
public IdentityHashMap(Map<? extends K, ? extends V> m) { |
|
266 |
// Allow for a bit of growth |
|
267 |
this((int) ((1 + m.size()) * 1.1)); |
|
268 |
putAll(m); |
|
269 |
} |
|
270 |
||
271 |
/** |
|
272 |
* Returns the number of key-value mappings in this identity hash map. |
|
273 |
* |
|
274 |
* @return the number of key-value mappings in this map |
|
275 |
*/ |
|
276 |
public int size() { |
|
277 |
return size; |
|
278 |
} |
|
279 |
||
280 |
/** |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
281 |
* Returns {@code true} if this identity hash map contains no key-value |
2 | 282 |
* mappings. |
283 |
* |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
284 |
* @return {@code true} if this identity hash map contains no key-value |
2 | 285 |
* mappings |
286 |
*/ |
|
287 |
public boolean isEmpty() { |
|
288 |
return size == 0; |
|
289 |
} |
|
290 |
||
291 |
/** |
|
292 |
* Returns index for Object x. |
|
293 |
*/ |
|
294 |
private static int hash(Object x, int length) { |
|
295 |
int h = System.identityHashCode(x); |
|
296 |
// Multiply by -127, and left-shift to use least bit as part of hash |
|
297 |
return ((h << 1) - (h << 8)) & (length - 1); |
|
298 |
} |
|
299 |
||
300 |
/** |
|
301 |
* Circularly traverses table of size len. |
|
302 |
*/ |
|
303 |
private static int nextKeyIndex(int i, int len) { |
|
304 |
return (i + 2 < len ? i + 2 : 0); |
|
305 |
} |
|
306 |
||
307 |
/** |
|
308 |
* Returns the value to which the specified key is mapped, |
|
309 |
* or {@code null} if this map contains no mapping for the key. |
|
310 |
* |
|
311 |
* <p>More formally, if this map contains a mapping from a key |
|
312 |
* {@code k} to a value {@code v} such that {@code (key == k)}, |
|
313 |
* then this method returns {@code v}; otherwise it returns |
|
314 |
* {@code null}. (There can be at most one such mapping.) |
|
315 |
* |
|
316 |
* <p>A return value of {@code null} does not <i>necessarily</i> |
|
317 |
* indicate that the map contains no mapping for the key; it's also |
|
318 |
* possible that the map explicitly maps the key to {@code null}. |
|
319 |
* The {@link #containsKey containsKey} operation may be used to |
|
320 |
* distinguish these two cases. |
|
321 |
* |
|
322 |
* @see #put(Object, Object) |
|
323 |
*/ |
|
12448 | 324 |
@SuppressWarnings("unchecked") |
2 | 325 |
public V get(Object key) { |
326 |
Object k = maskNull(key); |
|
327 |
Object[] tab = table; |
|
328 |
int len = tab.length; |
|
329 |
int i = hash(k, len); |
|
330 |
while (true) { |
|
331 |
Object item = tab[i]; |
|
332 |
if (item == k) |
|
333 |
return (V) tab[i + 1]; |
|
334 |
if (item == null) |
|
335 |
return null; |
|
336 |
i = nextKeyIndex(i, len); |
|
337 |
} |
|
338 |
} |
|
339 |
||
340 |
/** |
|
341 |
* Tests whether the specified object reference is a key in this identity |
|
342 |
* hash map. |
|
343 |
* |
|
344 |
* @param key possible key |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
345 |
* @return {@code true} if the specified object reference is a key |
2 | 346 |
* in this map |
347 |
* @see #containsValue(Object) |
|
348 |
*/ |
|
349 |
public boolean containsKey(Object key) { |
|
350 |
Object k = maskNull(key); |
|
351 |
Object[] tab = table; |
|
352 |
int len = tab.length; |
|
353 |
int i = hash(k, len); |
|
354 |
while (true) { |
|
355 |
Object item = tab[i]; |
|
356 |
if (item == k) |
|
357 |
return true; |
|
358 |
if (item == null) |
|
359 |
return false; |
|
360 |
i = nextKeyIndex(i, len); |
|
361 |
} |
|
362 |
} |
|
363 |
||
364 |
/** |
|
365 |
* Tests whether the specified object reference is a value in this identity |
|
366 |
* hash map. |
|
367 |
* |
|
368 |
* @param value value whose presence in this map is to be tested |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
369 |
* @return {@code true} if this map maps one or more keys to the |
2 | 370 |
* specified object reference |
371 |
* @see #containsKey(Object) |
|
372 |
*/ |
|
373 |
public boolean containsValue(Object value) { |
|
374 |
Object[] tab = table; |
|
494
320ce398f07e
6691215: (coll) IdentityHashMap.containsValue(null) returns true when null value not present
martin
parents:
65
diff
changeset
|
375 |
for (int i = 1; i < tab.length; i += 2) |
320ce398f07e
6691215: (coll) IdentityHashMap.containsValue(null) returns true when null value not present
martin
parents:
65
diff
changeset
|
376 |
if (tab[i] == value && tab[i - 1] != null) |
2 | 377 |
return true; |
378 |
||
379 |
return false; |
|
380 |
} |
|
381 |
||
382 |
/** |
|
383 |
* Tests if the specified key-value mapping is in the map. |
|
384 |
* |
|
385 |
* @param key possible key |
|
386 |
* @param value possible value |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
387 |
* @return {@code true} if and only if the specified key-value |
2 | 388 |
* mapping is in the map |
389 |
*/ |
|
390 |
private boolean containsMapping(Object key, Object value) { |
|
391 |
Object k = maskNull(key); |
|
392 |
Object[] tab = table; |
|
393 |
int len = tab.length; |
|
394 |
int i = hash(k, len); |
|
395 |
while (true) { |
|
396 |
Object item = tab[i]; |
|
397 |
if (item == k) |
|
398 |
return tab[i + 1] == value; |
|
399 |
if (item == null) |
|
400 |
return false; |
|
401 |
i = nextKeyIndex(i, len); |
|
402 |
} |
|
403 |
} |
|
404 |
||
405 |
/** |
|
406 |
* Associates the specified value with the specified key in this identity |
|
407 |
* hash map. If the map previously contained a mapping for the key, the |
|
408 |
* old value is replaced. |
|
409 |
* |
|
410 |
* @param key the key with which the specified value is to be associated |
|
411 |
* @param value the value to be associated with the specified key |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
412 |
* @return the previous value associated with {@code key}, or |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
413 |
* {@code null} if there was no mapping for {@code key}. |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
414 |
* (A {@code null} return can also indicate that the map |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
415 |
* previously associated {@code null} with {@code key}.) |
2 | 416 |
* @see Object#equals(Object) |
417 |
* @see #get(Object) |
|
418 |
* @see #containsKey(Object) |
|
419 |
*/ |
|
420 |
public V put(K key, V value) { |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
421 |
final Object k = maskNull(key); |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
422 |
|
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
423 |
retryAfterResize: for (;;) { |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
424 |
final Object[] tab = table; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
425 |
final int len = tab.length; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
426 |
int i = hash(k, len); |
2 | 427 |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
428 |
for (Object item; (item = tab[i]) != null; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
429 |
i = nextKeyIndex(i, len)) { |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
430 |
if (item == k) { |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
431 |
@SuppressWarnings("unchecked") |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
432 |
V oldValue = (V) tab[i + 1]; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
433 |
tab[i + 1] = value; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
434 |
return oldValue; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
435 |
} |
2 | 436 |
} |
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
437 |
|
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
438 |
final int s = size + 1; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
439 |
// Use optimized form of 3 * s. |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
440 |
// Next capacity is len, 2 * current capacity. |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
441 |
if (s + (s << 1) > len && resize(len)) |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
442 |
continue retryAfterResize; |
2 | 443 |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
444 |
modCount++; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
445 |
tab[i] = k; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
446 |
tab[i + 1] = value; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
447 |
size = s; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
448 |
return null; |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
449 |
} |
2 | 450 |
} |
451 |
||
452 |
/** |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
453 |
* Resizes the table if necessary to hold given capacity. |
2 | 454 |
* |
455 |
* @param newCapacity the new capacity, must be a power of two. |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
456 |
* @return whether a resize did in fact take place |
2 | 457 |
*/ |
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
458 |
private boolean resize(int newCapacity) { |
2 | 459 |
// assert (newCapacity & -newCapacity) == newCapacity; // power of 2 |
460 |
int newLength = newCapacity * 2; |
|
461 |
||
462 |
Object[] oldTable = table; |
|
463 |
int oldLength = oldTable.length; |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
464 |
if (oldLength == 2 * MAXIMUM_CAPACITY) { // can't expand any further |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
465 |
if (size == MAXIMUM_CAPACITY - 1) |
2 | 466 |
throw new IllegalStateException("Capacity exhausted."); |
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
467 |
return false; |
2 | 468 |
} |
469 |
if (oldLength >= newLength) |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
470 |
return false; |
2 | 471 |
|
472 |
Object[] newTable = new Object[newLength]; |
|
473 |
||
474 |
for (int j = 0; j < oldLength; j += 2) { |
|
475 |
Object key = oldTable[j]; |
|
476 |
if (key != null) { |
|
477 |
Object value = oldTable[j+1]; |
|
478 |
oldTable[j] = null; |
|
479 |
oldTable[j+1] = null; |
|
480 |
int i = hash(key, newLength); |
|
481 |
while (newTable[i] != null) |
|
482 |
i = nextKeyIndex(i, newLength); |
|
483 |
newTable[i] = key; |
|
484 |
newTable[i + 1] = value; |
|
485 |
} |
|
486 |
} |
|
487 |
table = newTable; |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
488 |
return true; |
2 | 489 |
} |
490 |
||
491 |
/** |
|
492 |
* Copies all of the mappings from the specified map to this map. |
|
493 |
* These mappings will replace any mappings that this map had for |
|
494 |
* any of the keys currently in the specified map. |
|
495 |
* |
|
496 |
* @param m mappings to be stored in this map |
|
497 |
* @throws NullPointerException if the specified map is null |
|
498 |
*/ |
|
499 |
public void putAll(Map<? extends K, ? extends V> m) { |
|
500 |
int n = m.size(); |
|
501 |
if (n == 0) |
|
502 |
return; |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
503 |
if (n > size) |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
504 |
resize(capacity(n)); // conservatively pre-expand |
2 | 505 |
|
506 |
for (Entry<? extends K, ? extends V> e : m.entrySet()) |
|
507 |
put(e.getKey(), e.getValue()); |
|
508 |
} |
|
509 |
||
510 |
/** |
|
511 |
* Removes the mapping for this key from this map if present. |
|
512 |
* |
|
513 |
* @param key key whose mapping is to be removed from the map |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
514 |
* @return the previous value associated with {@code key}, or |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
515 |
* {@code null} if there was no mapping for {@code key}. |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
516 |
* (A {@code null} return can also indicate that the map |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
517 |
* previously associated {@code null} with {@code key}.) |
2 | 518 |
*/ |
519 |
public V remove(Object key) { |
|
520 |
Object k = maskNull(key); |
|
521 |
Object[] tab = table; |
|
522 |
int len = tab.length; |
|
523 |
int i = hash(k, len); |
|
524 |
||
525 |
while (true) { |
|
526 |
Object item = tab[i]; |
|
527 |
if (item == k) { |
|
528 |
modCount++; |
|
529 |
size--; |
|
12448 | 530 |
@SuppressWarnings("unchecked") |
531 |
V oldValue = (V) tab[i + 1]; |
|
2 | 532 |
tab[i + 1] = null; |
533 |
tab[i] = null; |
|
534 |
closeDeletion(i); |
|
535 |
return oldValue; |
|
536 |
} |
|
537 |
if (item == null) |
|
538 |
return null; |
|
539 |
i = nextKeyIndex(i, len); |
|
540 |
} |
|
541 |
} |
|
542 |
||
543 |
/** |
|
544 |
* Removes the specified key-value mapping from the map if it is present. |
|
545 |
* |
|
546 |
* @param key possible key |
|
547 |
* @param value possible value |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
548 |
* @return {@code true} if and only if the specified key-value |
2 | 549 |
* mapping was in the map |
550 |
*/ |
|
551 |
private boolean removeMapping(Object key, Object value) { |
|
552 |
Object k = maskNull(key); |
|
553 |
Object[] tab = table; |
|
554 |
int len = tab.length; |
|
555 |
int i = hash(k, len); |
|
556 |
||
557 |
while (true) { |
|
558 |
Object item = tab[i]; |
|
559 |
if (item == k) { |
|
560 |
if (tab[i + 1] != value) |
|
561 |
return false; |
|
562 |
modCount++; |
|
563 |
size--; |
|
564 |
tab[i] = null; |
|
565 |
tab[i + 1] = null; |
|
566 |
closeDeletion(i); |
|
567 |
return true; |
|
568 |
} |
|
569 |
if (item == null) |
|
570 |
return false; |
|
571 |
i = nextKeyIndex(i, len); |
|
572 |
} |
|
573 |
} |
|
574 |
||
575 |
/** |
|
576 |
* Rehash all possibly-colliding entries following a |
|
577 |
* deletion. This preserves the linear-probe |
|
578 |
* collision properties required by get, put, etc. |
|
579 |
* |
|
580 |
* @param d the index of a newly empty deleted slot |
|
581 |
*/ |
|
582 |
private void closeDeletion(int d) { |
|
583 |
// Adapted from Knuth Section 6.4 Algorithm R |
|
584 |
Object[] tab = table; |
|
585 |
int len = tab.length; |
|
586 |
||
587 |
// Look for items to swap into newly vacated slot |
|
588 |
// starting at index immediately following deletion, |
|
589 |
// and continuing until a null slot is seen, indicating |
|
590 |
// the end of a run of possibly-colliding keys. |
|
591 |
Object item; |
|
592 |
for (int i = nextKeyIndex(d, len); (item = tab[i]) != null; |
|
593 |
i = nextKeyIndex(i, len) ) { |
|
594 |
// The following test triggers if the item at slot i (which |
|
595 |
// hashes to be at slot r) should take the spot vacated by d. |
|
596 |
// If so, we swap it in, and then continue with d now at the |
|
597 |
// newly vacated i. This process will terminate when we hit |
|
598 |
// the null slot at the end of this run. |
|
599 |
// The test is messy because we are using a circular table. |
|
600 |
int r = hash(item, len); |
|
601 |
if ((i < r && (r <= d || d <= i)) || (r <= d && d <= i)) { |
|
602 |
tab[d] = item; |
|
603 |
tab[d + 1] = tab[i + 1]; |
|
604 |
tab[i] = null; |
|
605 |
tab[i + 1] = null; |
|
606 |
d = i; |
|
607 |
} |
|
608 |
} |
|
609 |
} |
|
610 |
||
611 |
/** |
|
612 |
* Removes all of the mappings from this map. |
|
613 |
* The map will be empty after this call returns. |
|
614 |
*/ |
|
615 |
public void clear() { |
|
616 |
modCount++; |
|
617 |
Object[] tab = table; |
|
618 |
for (int i = 0; i < tab.length; i++) |
|
619 |
tab[i] = null; |
|
620 |
size = 0; |
|
621 |
} |
|
622 |
||
623 |
/** |
|
624 |
* Compares the specified object with this map for equality. Returns |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
625 |
* {@code true} if the given object is also a map and the two maps |
2 | 626 |
* represent identical object-reference mappings. More formally, this |
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
627 |
* map is equal to another map {@code m} if and only if |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
628 |
* {@code this.entrySet().equals(m.entrySet())}. |
2 | 629 |
* |
630 |
* <p><b>Owing to the reference-equality-based semantics of this map it is |
|
631 |
* possible that the symmetry and transitivity requirements of the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
632 |
* {@code Object.equals} contract may be violated if this map is compared |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
633 |
* to a normal map. However, the {@code Object.equals} contract is |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
634 |
* guaranteed to hold among {@code IdentityHashMap} instances.</b> |
2 | 635 |
* |
636 |
* @param o object to be compared for equality with this map |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
637 |
* @return {@code true} if the specified object is equal to this map |
2 | 638 |
* @see Object#equals(Object) |
639 |
*/ |
|
640 |
public boolean equals(Object o) { |
|
641 |
if (o == this) { |
|
642 |
return true; |
|
643 |
} else if (o instanceof IdentityHashMap) { |
|
12448 | 644 |
IdentityHashMap<?,?> m = (IdentityHashMap<?,?>) o; |
2 | 645 |
if (m.size() != size) |
646 |
return false; |
|
647 |
||
648 |
Object[] tab = m.table; |
|
649 |
for (int i = 0; i < tab.length; i+=2) { |
|
650 |
Object k = tab[i]; |
|
651 |
if (k != null && !containsMapping(k, tab[i + 1])) |
|
652 |
return false; |
|
653 |
} |
|
654 |
return true; |
|
655 |
} else if (o instanceof Map) { |
|
12448 | 656 |
Map<?,?> m = (Map<?,?>)o; |
2 | 657 |
return entrySet().equals(m.entrySet()); |
658 |
} else { |
|
659 |
return false; // o is not a Map |
|
660 |
} |
|
661 |
} |
|
662 |
||
663 |
/** |
|
664 |
* Returns the hash code value for this map. The hash code of a map is |
|
665 |
* defined to be the sum of the hash codes of each entry in the map's |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
666 |
* {@code entrySet()} view. This ensures that {@code m1.equals(m2)} |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
667 |
* implies that {@code m1.hashCode()==m2.hashCode()} for any two |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
668 |
* {@code IdentityHashMap} instances {@code m1} and {@code m2}, as |
2 | 669 |
* required by the general contract of {@link Object#hashCode}. |
670 |
* |
|
671 |
* <p><b>Owing to the reference-equality-based semantics of the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
672 |
* {@code Map.Entry} instances in the set returned by this map's |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
673 |
* {@code entrySet} method, it is possible that the contractual |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
674 |
* requirement of {@code Object.hashCode} mentioned in the previous |
2 | 675 |
* paragraph will be violated if one of the two objects being compared is |
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
676 |
* an {@code IdentityHashMap} instance and the other is a normal map.</b> |
2 | 677 |
* |
678 |
* @return the hash code value for this map |
|
679 |
* @see Object#equals(Object) |
|
680 |
* @see #equals(Object) |
|
681 |
*/ |
|
682 |
public int hashCode() { |
|
683 |
int result = 0; |
|
684 |
Object[] tab = table; |
|
685 |
for (int i = 0; i < tab.length; i +=2) { |
|
686 |
Object key = tab[i]; |
|
687 |
if (key != null) { |
|
688 |
Object k = unmaskNull(key); |
|
689 |
result += System.identityHashCode(k) ^ |
|
690 |
System.identityHashCode(tab[i + 1]); |
|
691 |
} |
|
692 |
} |
|
693 |
return result; |
|
694 |
} |
|
695 |
||
696 |
/** |
|
697 |
* Returns a shallow copy of this identity hash map: the keys and values |
|
698 |
* themselves are not cloned. |
|
699 |
* |
|
700 |
* @return a shallow copy of this map |
|
701 |
*/ |
|
702 |
public Object clone() { |
|
703 |
try { |
|
12448 | 704 |
IdentityHashMap<?,?> m = (IdentityHashMap<?,?>) super.clone(); |
2 | 705 |
m.entrySet = null; |
51 | 706 |
m.table = table.clone(); |
2 | 707 |
return m; |
708 |
} catch (CloneNotSupportedException e) { |
|
10419
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9275
diff
changeset
|
709 |
throw new InternalError(e); |
2 | 710 |
} |
711 |
} |
|
712 |
||
713 |
private abstract class IdentityHashMapIterator<T> implements Iterator<T> { |
|
714 |
int index = (size != 0 ? 0 : table.length); // current slot. |
|
715 |
int expectedModCount = modCount; // to support fast-fail |
|
716 |
int lastReturnedIndex = -1; // to allow remove() |
|
717 |
boolean indexValid; // To avoid unnecessary next computation |
|
718 |
Object[] traversalTable = table; // reference to main table or copy |
|
719 |
||
720 |
public boolean hasNext() { |
|
721 |
Object[] tab = traversalTable; |
|
722 |
for (int i = index; i < tab.length; i+=2) { |
|
723 |
Object key = tab[i]; |
|
724 |
if (key != null) { |
|
725 |
index = i; |
|
726 |
return indexValid = true; |
|
727 |
} |
|
728 |
} |
|
729 |
index = tab.length; |
|
730 |
return false; |
|
731 |
} |
|
732 |
||
733 |
protected int nextIndex() { |
|
734 |
if (modCount != expectedModCount) |
|
735 |
throw new ConcurrentModificationException(); |
|
736 |
if (!indexValid && !hasNext()) |
|
737 |
throw new NoSuchElementException(); |
|
738 |
||
739 |
indexValid = false; |
|
740 |
lastReturnedIndex = index; |
|
741 |
index += 2; |
|
742 |
return lastReturnedIndex; |
|
743 |
} |
|
744 |
||
745 |
public void remove() { |
|
746 |
if (lastReturnedIndex == -1) |
|
747 |
throw new IllegalStateException(); |
|
748 |
if (modCount != expectedModCount) |
|
749 |
throw new ConcurrentModificationException(); |
|
750 |
||
751 |
expectedModCount = ++modCount; |
|
752 |
int deletedSlot = lastReturnedIndex; |
|
753 |
lastReturnedIndex = -1; |
|
754 |
// back up index to revisit new contents after deletion |
|
755 |
index = deletedSlot; |
|
756 |
indexValid = false; |
|
757 |
||
758 |
// Removal code proceeds as in closeDeletion except that |
|
759 |
// it must catch the rare case where an element already |
|
760 |
// seen is swapped into a vacant slot that will be later |
|
761 |
// traversed by this iterator. We cannot allow future |
|
762 |
// next() calls to return it again. The likelihood of |
|
763 |
// this occurring under 2/3 load factor is very slim, but |
|
764 |
// when it does happen, we must make a copy of the rest of |
|
765 |
// the table to use for the rest of the traversal. Since |
|
766 |
// this can only happen when we are near the end of the table, |
|
767 |
// even in these rare cases, this is not very expensive in |
|
768 |
// time or space. |
|
769 |
||
770 |
Object[] tab = traversalTable; |
|
771 |
int len = tab.length; |
|
772 |
||
773 |
int d = deletedSlot; |
|
12448 | 774 |
Object key = tab[d]; |
2 | 775 |
tab[d] = null; // vacate the slot |
776 |
tab[d + 1] = null; |
|
777 |
||
778 |
// If traversing a copy, remove in real table. |
|
779 |
// We can skip gap-closure on copy. |
|
780 |
if (tab != IdentityHashMap.this.table) { |
|
781 |
IdentityHashMap.this.remove(key); |
|
782 |
expectedModCount = modCount; |
|
783 |
return; |
|
784 |
} |
|
785 |
||
58
55e9cd9ade0b
6612102: (coll) IdentityHashMap.iterator().remove() might decrement size twice
martin
parents:
51
diff
changeset
|
786 |
size--; |
55e9cd9ade0b
6612102: (coll) IdentityHashMap.iterator().remove() might decrement size twice
martin
parents:
51
diff
changeset
|
787 |
|
2 | 788 |
Object item; |
789 |
for (int i = nextKeyIndex(d, len); (item = tab[i]) != null; |
|
790 |
i = nextKeyIndex(i, len)) { |
|
791 |
int r = hash(item, len); |
|
792 |
// See closeDeletion for explanation of this conditional |
|
793 |
if ((i < r && (r <= d || d <= i)) || |
|
794 |
(r <= d && d <= i)) { |
|
795 |
||
796 |
// If we are about to swap an already-seen element |
|
797 |
// into a slot that may later be returned by next(), |
|
798 |
// then clone the rest of table for use in future |
|
799 |
// next() calls. It is OK that our copy will have |
|
800 |
// a gap in the "wrong" place, since it will never |
|
801 |
// be used for searching anyway. |
|
802 |
||
803 |
if (i < deletedSlot && d >= deletedSlot && |
|
804 |
traversalTable == IdentityHashMap.this.table) { |
|
805 |
int remaining = len - deletedSlot; |
|
806 |
Object[] newTable = new Object[remaining]; |
|
807 |
System.arraycopy(tab, deletedSlot, |
|
808 |
newTable, 0, remaining); |
|
809 |
traversalTable = newTable; |
|
810 |
index = 0; |
|
811 |
} |
|
812 |
||
813 |
tab[d] = item; |
|
814 |
tab[d + 1] = tab[i + 1]; |
|
815 |
tab[i] = null; |
|
816 |
tab[i + 1] = null; |
|
817 |
d = i; |
|
818 |
} |
|
819 |
} |
|
820 |
} |
|
821 |
} |
|
822 |
||
823 |
private class KeyIterator extends IdentityHashMapIterator<K> { |
|
12448 | 824 |
@SuppressWarnings("unchecked") |
2 | 825 |
public K next() { |
826 |
return (K) unmaskNull(traversalTable[nextIndex()]); |
|
827 |
} |
|
828 |
} |
|
829 |
||
830 |
private class ValueIterator extends IdentityHashMapIterator<V> { |
|
12448 | 831 |
@SuppressWarnings("unchecked") |
2 | 832 |
public V next() { |
833 |
return (V) traversalTable[nextIndex() + 1]; |
|
834 |
} |
|
835 |
} |
|
836 |
||
837 |
private class EntryIterator |
|
838 |
extends IdentityHashMapIterator<Map.Entry<K,V>> |
|
839 |
{ |
|
23746 | 840 |
private Entry lastReturnedEntry; |
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
841 |
|
2 | 842 |
public Map.Entry<K,V> next() { |
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
843 |
lastReturnedEntry = new Entry(nextIndex()); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
844 |
return lastReturnedEntry; |
2 | 845 |
} |
846 |
||
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
847 |
public void remove() { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
848 |
lastReturnedIndex = |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
849 |
((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
850 |
super.remove(); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
851 |
lastReturnedEntry.index = lastReturnedIndex; |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
852 |
lastReturnedEntry = null; |
2 | 853 |
} |
854 |
||
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
855 |
private class Entry implements Map.Entry<K,V> { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
856 |
private int index; |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
857 |
|
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
858 |
private Entry(int index) { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
859 |
this.index = index; |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
860 |
} |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
861 |
|
12448 | 862 |
@SuppressWarnings("unchecked") |
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
863 |
public K getKey() { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
864 |
checkIndexForEntryUse(); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
865 |
return (K) unmaskNull(traversalTable[index]); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
866 |
} |
2 | 867 |
|
12448 | 868 |
@SuppressWarnings("unchecked") |
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
869 |
public V getValue() { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
870 |
checkIndexForEntryUse(); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
871 |
return (V) traversalTable[index+1]; |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
872 |
} |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
873 |
|
12448 | 874 |
@SuppressWarnings("unchecked") |
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
875 |
public V setValue(V value) { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
876 |
checkIndexForEntryUse(); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
877 |
V oldValue = (V) traversalTable[index+1]; |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
878 |
traversalTable[index+1] = value; |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
879 |
// if shadowing, force into main table |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
880 |
if (traversalTable != IdentityHashMap.this.table) |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
881 |
put((K) traversalTable[index], value); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
882 |
return oldValue; |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
883 |
} |
2 | 884 |
|
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
885 |
public boolean equals(Object o) { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
886 |
if (index < 0) |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
887 |
return super.equals(o); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
888 |
|
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
889 |
if (!(o instanceof Map.Entry)) |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
890 |
return false; |
12448 | 891 |
Map.Entry<?,?> e = (Map.Entry<?,?>)o; |
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
892 |
return (e.getKey() == unmaskNull(traversalTable[index]) && |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
893 |
e.getValue() == traversalTable[index+1]); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
894 |
} |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
895 |
|
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
896 |
public int hashCode() { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
897 |
if (lastReturnedIndex < 0) |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
898 |
return super.hashCode(); |
2 | 899 |
|
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
900 |
return (System.identityHashCode(unmaskNull(traversalTable[index])) ^ |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
901 |
System.identityHashCode(traversalTable[index+1])); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
902 |
} |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
903 |
|
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
904 |
public String toString() { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
905 |
if (index < 0) |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
906 |
return super.toString(); |
2 | 907 |
|
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
908 |
return (unmaskNull(traversalTable[index]) + "=" |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
909 |
+ traversalTable[index+1]); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
910 |
} |
2 | 911 |
|
9235
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
912 |
private void checkIndexForEntryUse() { |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
913 |
if (index < 0) |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
914 |
throw new IllegalStateException("Entry was removed"); |
ddd556c97e6c
6312706: Map entrySet iterators should return different entries on each call to next()
mduigou
parents:
7803
diff
changeset
|
915 |
} |
2 | 916 |
} |
917 |
} |
|
918 |
||
919 |
// Views |
|
920 |
||
921 |
/** |
|
922 |
* This field is initialized to contain an instance of the entry set |
|
923 |
* view the first time this view is requested. The view is stateless, |
|
924 |
* so there's no reason to create more than one. |
|
925 |
*/ |
|
23746 | 926 |
private transient Set<Map.Entry<K,V>> entrySet; |
2 | 927 |
|
928 |
/** |
|
929 |
* Returns an identity-based set view of the keys contained in this map. |
|
930 |
* The set is backed by the map, so changes to the map are reflected in |
|
931 |
* the set, and vice-versa. If the map is modified while an iteration |
|
932 |
* over the set is in progress, the results of the iteration are |
|
933 |
* undefined. The set supports element removal, which removes the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
934 |
* corresponding mapping from the map, via the {@code Iterator.remove}, |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
935 |
* {@code Set.remove}, {@code removeAll}, {@code retainAll}, and |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
936 |
* {@code clear} methods. It does not support the {@code add} or |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
937 |
* {@code addAll} methods. |
2 | 938 |
* |
939 |
* <p><b>While the object returned by this method implements the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
940 |
* {@code Set} interface, it does <i>not</i> obey {@code Set's} general |
2 | 941 |
* contract. Like its backing map, the set returned by this method |
942 |
* defines element equality as reference-equality rather than |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
943 |
* object-equality. This affects the behavior of its {@code contains}, |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
944 |
* {@code remove}, {@code containsAll}, {@code equals}, and |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
945 |
* {@code hashCode} methods.</b> |
2 | 946 |
* |
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
947 |
* <p><b>The {@code equals} method of the returned set returns {@code true} |
2 | 948 |
* only if the specified object is a set containing exactly the same |
949 |
* object references as the returned set. The symmetry and transitivity |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
950 |
* requirements of the {@code Object.equals} contract may be violated if |
2 | 951 |
* the set returned by this method is compared to a normal set. However, |
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
952 |
* the {@code Object.equals} contract is guaranteed to hold among sets |
2 | 953 |
* returned by this method.</b> |
954 |
* |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
955 |
* <p>The {@code hashCode} method of the returned set returns the sum of |
2 | 956 |
* the <i>identity hashcodes</i> of the elements in the set, rather than |
957 |
* the sum of their hashcodes. This is mandated by the change in the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
958 |
* semantics of the {@code equals} method, in order to enforce the |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
959 |
* general contract of the {@code Object.hashCode} method among sets |
2 | 960 |
* returned by this method. |
961 |
* |
|
962 |
* @return an identity-based set view of the keys contained in this map |
|
963 |
* @see Object#equals(Object) |
|
964 |
* @see System#identityHashCode(Object) |
|
965 |
*/ |
|
966 |
public Set<K> keySet() { |
|
967 |
Set<K> ks = keySet; |
|
34712
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
968 |
if (ks == null) { |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
969 |
ks = new KeySet(); |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
970 |
keySet = ks; |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
971 |
} |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
972 |
return ks; |
2 | 973 |
} |
974 |
||
975 |
private class KeySet extends AbstractSet<K> { |
|
976 |
public Iterator<K> iterator() { |
|
977 |
return new KeyIterator(); |
|
978 |
} |
|
979 |
public int size() { |
|
980 |
return size; |
|
981 |
} |
|
982 |
public boolean contains(Object o) { |
|
983 |
return containsKey(o); |
|
984 |
} |
|
985 |
public boolean remove(Object o) { |
|
986 |
int oldSize = size; |
|
987 |
IdentityHashMap.this.remove(o); |
|
988 |
return size != oldSize; |
|
989 |
} |
|
990 |
/* |
|
991 |
* Must revert from AbstractSet's impl to AbstractCollection's, as |
|
992 |
* the former contains an optimization that results in incorrect |
|
993 |
* behavior when c is a smaller "normal" (non-identity-based) Set. |
|
994 |
*/ |
|
995 |
public boolean removeAll(Collection<?> c) { |
|
19855 | 996 |
Objects.requireNonNull(c); |
2 | 997 |
boolean modified = false; |
51 | 998 |
for (Iterator<K> i = iterator(); i.hasNext(); ) { |
2 | 999 |
if (c.contains(i.next())) { |
1000 |
i.remove(); |
|
1001 |
modified = true; |
|
1002 |
} |
|
1003 |
} |
|
1004 |
return modified; |
|
1005 |
} |
|
1006 |
public void clear() { |
|
1007 |
IdentityHashMap.this.clear(); |
|
1008 |
} |
|
1009 |
public int hashCode() { |
|
1010 |
int result = 0; |
|
1011 |
for (K key : this) |
|
1012 |
result += System.identityHashCode(key); |
|
1013 |
return result; |
|
1014 |
} |
|
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1015 |
public Object[] toArray() { |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1016 |
return toArray(new Object[0]); |
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1017 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1018 |
@SuppressWarnings("unchecked") |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1019 |
public <T> T[] toArray(T[] a) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1020 |
int expectedModCount = modCount; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1021 |
int size = size(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1022 |
if (a.length < size) |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1023 |
a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1024 |
Object[] tab = table; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1025 |
int ti = 0; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1026 |
for (int si = 0; si < tab.length; si += 2) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1027 |
Object key; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1028 |
if ((key = tab[si]) != null) { // key present ? |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1029 |
// more elements than expected -> concurrent modification from other thread |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1030 |
if (ti >= size) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1031 |
throw new ConcurrentModificationException(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1032 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1033 |
a[ti++] = (T) unmaskNull(key); // unmask key |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1034 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1035 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1036 |
// fewer elements than expected or concurrent modification from other thread detected |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1037 |
if (ti < size || expectedModCount != modCount) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1038 |
throw new ConcurrentModificationException(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1039 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1040 |
// final null marker as per spec |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1041 |
if (ti < a.length) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1042 |
a[ti] = null; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1043 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1044 |
return a; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1045 |
} |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1046 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1047 |
public Spliterator<K> spliterator() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1048 |
return new KeySpliterator<>(IdentityHashMap.this, 0, -1, 0, 0); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1049 |
} |
2 | 1050 |
} |
1051 |
||
1052 |
/** |
|
1053 |
* Returns a {@link Collection} view of the values contained in this map. |
|
1054 |
* The collection is backed by the map, so changes to the map are |
|
1055 |
* reflected in the collection, and vice-versa. If the map is |
|
1056 |
* modified while an iteration over the collection is in progress, |
|
1057 |
* the results of the iteration are undefined. The collection |
|
1058 |
* supports element removal, which removes the corresponding |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1059 |
* mapping from the map, via the {@code Iterator.remove}, |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1060 |
* {@code Collection.remove}, {@code removeAll}, |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1061 |
* {@code retainAll} and {@code clear} methods. It does not |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1062 |
* support the {@code add} or {@code addAll} methods. |
2 | 1063 |
* |
1064 |
* <p><b>While the object returned by this method implements the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1065 |
* {@code Collection} interface, it does <i>not</i> obey |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1066 |
* {@code Collection's} general contract. Like its backing map, |
2 | 1067 |
* the collection returned by this method defines element equality as |
1068 |
* reference-equality rather than object-equality. This affects the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1069 |
* behavior of its {@code contains}, {@code remove} and |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1070 |
* {@code containsAll} methods.</b> |
2 | 1071 |
*/ |
1072 |
public Collection<V> values() { |
|
1073 |
Collection<V> vs = values; |
|
34712
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
1074 |
if (vs == null) { |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
1075 |
vs = new Values(); |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
1076 |
values = vs; |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
1077 |
} |
b183cfd1ce17
8145539: (coll) AbstractMap.keySet and .values should not be volatile
shade
parents:
32108
diff
changeset
|
1078 |
return vs; |
2 | 1079 |
} |
1080 |
||
1081 |
private class Values extends AbstractCollection<V> { |
|
1082 |
public Iterator<V> iterator() { |
|
1083 |
return new ValueIterator(); |
|
1084 |
} |
|
1085 |
public int size() { |
|
1086 |
return size; |
|
1087 |
} |
|
1088 |
public boolean contains(Object o) { |
|
1089 |
return containsValue(o); |
|
1090 |
} |
|
1091 |
public boolean remove(Object o) { |
|
51 | 1092 |
for (Iterator<V> i = iterator(); i.hasNext(); ) { |
2 | 1093 |
if (i.next() == o) { |
1094 |
i.remove(); |
|
1095 |
return true; |
|
1096 |
} |
|
1097 |
} |
|
1098 |
return false; |
|
1099 |
} |
|
1100 |
public void clear() { |
|
1101 |
IdentityHashMap.this.clear(); |
|
1102 |
} |
|
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1103 |
public Object[] toArray() { |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1104 |
return toArray(new Object[0]); |
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1105 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1106 |
@SuppressWarnings("unchecked") |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1107 |
public <T> T[] toArray(T[] a) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1108 |
int expectedModCount = modCount; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1109 |
int size = size(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1110 |
if (a.length < size) |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1111 |
a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1112 |
Object[] tab = table; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1113 |
int ti = 0; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1114 |
for (int si = 0; si < tab.length; si += 2) { |
16042
0bf6469a1cfb
8008785: IdentityHashMap.values().toArray(V[]) broken by JDK-8008167
mduigou
parents:
15997
diff
changeset
|
1115 |
if (tab[si] != null) { // key present ? |
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1116 |
// more elements than expected -> concurrent modification from other thread |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1117 |
if (ti >= size) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1118 |
throw new ConcurrentModificationException(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1119 |
} |
16042
0bf6469a1cfb
8008785: IdentityHashMap.values().toArray(V[]) broken by JDK-8008167
mduigou
parents:
15997
diff
changeset
|
1120 |
a[ti++] = (T) tab[si+1]; // copy value |
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1121 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1122 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1123 |
// fewer elements than expected or concurrent modification from other thread detected |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1124 |
if (ti < size || expectedModCount != modCount) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1125 |
throw new ConcurrentModificationException(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1126 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1127 |
// final null marker as per spec |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1128 |
if (ti < a.length) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1129 |
a[ti] = null; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1130 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1131 |
return a; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1132 |
} |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1133 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1134 |
public Spliterator<V> spliterator() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1135 |
return new ValueSpliterator<>(IdentityHashMap.this, 0, -1, 0, 0); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1136 |
} |
2 | 1137 |
} |
1138 |
||
1139 |
/** |
|
1140 |
* Returns a {@link Set} view of the mappings contained in this map. |
|
1141 |
* Each element in the returned set is a reference-equality-based |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1142 |
* {@code Map.Entry}. The set is backed by the map, so changes |
2 | 1143 |
* to the map are reflected in the set, and vice-versa. If the |
1144 |
* map is modified while an iteration over the set is in progress, |
|
1145 |
* the results of the iteration are undefined. The set supports |
|
1146 |
* element removal, which removes the corresponding mapping from |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1147 |
* the map, via the {@code Iterator.remove}, {@code Set.remove}, |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1148 |
* {@code removeAll}, {@code retainAll} and {@code clear} |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1149 |
* methods. It does not support the {@code add} or |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1150 |
* {@code addAll} methods. |
2 | 1151 |
* |
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1152 |
* <p>Like the backing map, the {@code Map.Entry} objects in the set |
2 | 1153 |
* returned by this method define key and value equality as |
1154 |
* reference-equality rather than object-equality. This affects the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1155 |
* behavior of the {@code equals} and {@code hashCode} methods of these |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1156 |
* {@code Map.Entry} objects. A reference-equality based {@code Map.Entry |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1157 |
* e} is equal to an object {@code o} if and only if {@code o} is a |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1158 |
* {@code Map.Entry} and {@code e.getKey()==o.getKey() && |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1159 |
* e.getValue()==o.getValue()}. To accommodate these equals |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1160 |
* semantics, the {@code hashCode} method returns |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1161 |
* {@code System.identityHashCode(e.getKey()) ^ |
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1162 |
* System.identityHashCode(e.getValue())}. |
2 | 1163 |
* |
1164 |
* <p><b>Owing to the reference-equality-based semantics of the |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1165 |
* {@code Map.Entry} instances in the set returned by this method, |
2 | 1166 |
* it is possible that the symmetry and transitivity requirements of |
1167 |
* the {@link Object#equals(Object)} contract may be violated if any of |
|
1168 |
* the entries in the set is compared to a normal map entry, or if |
|
1169 |
* the set returned by this method is compared to a set of normal map |
|
1170 |
* entries (such as would be returned by a call to this method on a normal |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1171 |
* map). However, the {@code Object.equals} contract is guaranteed to |
2 | 1172 |
* hold among identity-based map entries, and among sets of such entries. |
1173 |
* </b> |
|
1174 |
* |
|
1175 |
* @return a set view of the identity-mappings contained in this map |
|
1176 |
*/ |
|
1177 |
public Set<Map.Entry<K,V>> entrySet() { |
|
1178 |
Set<Map.Entry<K,V>> es = entrySet; |
|
1179 |
if (es != null) |
|
1180 |
return es; |
|
1181 |
else |
|
1182 |
return entrySet = new EntrySet(); |
|
1183 |
} |
|
1184 |
||
1185 |
private class EntrySet extends AbstractSet<Map.Entry<K,V>> { |
|
1186 |
public Iterator<Map.Entry<K,V>> iterator() { |
|
1187 |
return new EntryIterator(); |
|
1188 |
} |
|
1189 |
public boolean contains(Object o) { |
|
1190 |
if (!(o instanceof Map.Entry)) |
|
1191 |
return false; |
|
12448 | 1192 |
Map.Entry<?,?> entry = (Map.Entry<?,?>)o; |
2 | 1193 |
return containsMapping(entry.getKey(), entry.getValue()); |
1194 |
} |
|
1195 |
public boolean remove(Object o) { |
|
1196 |
if (!(o instanceof Map.Entry)) |
|
1197 |
return false; |
|
12448 | 1198 |
Map.Entry<?,?> entry = (Map.Entry<?,?>)o; |
2 | 1199 |
return removeMapping(entry.getKey(), entry.getValue()); |
1200 |
} |
|
1201 |
public int size() { |
|
1202 |
return size; |
|
1203 |
} |
|
1204 |
public void clear() { |
|
1205 |
IdentityHashMap.this.clear(); |
|
1206 |
} |
|
1207 |
/* |
|
1208 |
* Must revert from AbstractSet's impl to AbstractCollection's, as |
|
1209 |
* the former contains an optimization that results in incorrect |
|
1210 |
* behavior when c is a smaller "normal" (non-identity-based) Set. |
|
1211 |
*/ |
|
1212 |
public boolean removeAll(Collection<?> c) { |
|
19855 | 1213 |
Objects.requireNonNull(c); |
2 | 1214 |
boolean modified = false; |
51 | 1215 |
for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) { |
2 | 1216 |
if (c.contains(i.next())) { |
1217 |
i.remove(); |
|
1218 |
modified = true; |
|
1219 |
} |
|
1220 |
} |
|
1221 |
return modified; |
|
1222 |
} |
|
1223 |
||
1224 |
public Object[] toArray() { |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1225 |
return toArray(new Object[0]); |
2 | 1226 |
} |
1227 |
||
1228 |
@SuppressWarnings("unchecked") |
|
1229 |
public <T> T[] toArray(T[] a) { |
|
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1230 |
int expectedModCount = modCount; |
2 | 1231 |
int size = size(); |
1232 |
if (a.length < size) |
|
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1233 |
a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1234 |
Object[] tab = table; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1235 |
int ti = 0; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1236 |
for (int si = 0; si < tab.length; si += 2) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1237 |
Object key; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1238 |
if ((key = tab[si]) != null) { // key present ? |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1239 |
// more elements than expected -> concurrent modification from other thread |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1240 |
if (ti >= size) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1241 |
throw new ConcurrentModificationException(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1242 |
} |
21655
55f32ae4f920
8028229: Fix more raw types lint warning in core libraries
darcy
parents:
19855
diff
changeset
|
1243 |
a[ti++] = (T) new AbstractMap.SimpleEntry<>(unmaskNull(key), tab[si + 1]); |
15997
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1244 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1245 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1246 |
// fewer elements than expected or concurrent modification from other thread detected |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1247 |
if (ti < size || expectedModCount != modCount) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1248 |
throw new ConcurrentModificationException(); |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1249 |
} |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1250 |
// final null marker as per spec |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1251 |
if (ti < a.length) { |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1252 |
a[ti] = null; |
39590b63ec4c
8008167: IdentityHashMap.[keySet|values|entrySet].toArray speed-up
mduigou
parents:
14342
diff
changeset
|
1253 |
} |
2 | 1254 |
return a; |
1255 |
} |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1256 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1257 |
public Spliterator<Map.Entry<K,V>> spliterator() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1258 |
return new EntrySpliterator<>(IdentityHashMap.this, 0, -1, 0, 0); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1259 |
} |
2 | 1260 |
} |
1261 |
||
1262 |
||
1263 |
private static final long serialVersionUID = 8188218128353913216L; |
|
1264 |
||
1265 |
/** |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1266 |
* Saves the state of the {@code IdentityHashMap} instance to a stream |
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
1267 |
* (i.e., serializes it). |
2 | 1268 |
* |
1269 |
* @serialData The <i>size</i> of the HashMap (the number of key-value |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1270 |
* mappings) ({@code int}), followed by the key (Object) and |
2 | 1271 |
* value (Object) for each key-value mapping represented by the |
1272 |
* IdentityHashMap. The key-value mappings are emitted in no |
|
1273 |
* particular order. |
|
1274 |
*/ |
|
1275 |
private void writeObject(java.io.ObjectOutputStream s) |
|
1276 |
throws java.io.IOException { |
|
1277 |
// Write out and any hidden stuff |
|
1278 |
s.defaultWriteObject(); |
|
1279 |
||
1280 |
// Write out size (number of Mappings) |
|
1281 |
s.writeInt(size); |
|
1282 |
||
1283 |
// Write out keys and values (alternating) |
|
1284 |
Object[] tab = table; |
|
1285 |
for (int i = 0; i < tab.length; i += 2) { |
|
1286 |
Object key = tab[i]; |
|
1287 |
if (key != null) { |
|
1288 |
s.writeObject(unmaskNull(key)); |
|
1289 |
s.writeObject(tab[i + 1]); |
|
1290 |
} |
|
1291 |
} |
|
1292 |
} |
|
1293 |
||
1294 |
/** |
|
32108
aa5490a167ee
8133188: docs: replace <tt> tags (obsolete in html5) for java.util
avstepan
parents:
25859
diff
changeset
|
1295 |
* Reconstitutes the {@code IdentityHashMap} instance from a stream (i.e., |
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
1296 |
* deserializes it). |
2 | 1297 |
*/ |
1298 |
private void readObject(java.io.ObjectInputStream s) |
|
1299 |
throws java.io.IOException, ClassNotFoundException { |
|
1300 |
// Read in any hidden stuff |
|
1301 |
s.defaultReadObject(); |
|
1302 |
||
1303 |
// Read in size (number of Mappings) |
|
1304 |
int size = s.readInt(); |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
1305 |
if (size < 0) |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
1306 |
throw new java.io.StreamCorruptedException |
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
1307 |
("Illegal mappings count: " + size); |
47423 | 1308 |
int cap = capacity(size); |
1309 |
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, cap); |
|
1310 |
init(cap); |
|
2 | 1311 |
|
1312 |
// Read the keys and values, and put the mappings in the table |
|
1313 |
for (int i=0; i<size; i++) { |
|
12448 | 1314 |
@SuppressWarnings("unchecked") |
1315 |
K key = (K) s.readObject(); |
|
1316 |
@SuppressWarnings("unchecked") |
|
1317 |
V value = (V) s.readObject(); |
|
2 | 1318 |
putForCreate(key, value); |
1319 |
} |
|
1320 |
} |
|
1321 |
||
1322 |
/** |
|
1323 |
* The put method for readObject. It does not resize the table, |
|
1324 |
* update modCount, etc. |
|
1325 |
*/ |
|
1326 |
private void putForCreate(K key, V value) |
|
25413
bb827716b9b9
6904367: (coll) IdentityHashMap is resized before exceeding the expected maximum size
igerasim
parents:
23746
diff
changeset
|
1327 |
throws java.io.StreamCorruptedException |
2 | 1328 |
{ |
12448 | 1329 |
Object k = maskNull(key); |
2 | 1330 |
Object[] tab = table; |
1331 |
int len = tab.length; |
|
1332 |
int i = hash(k, len); |
|
1333 |
||
1334 |
Object item; |
|
1335 |
while ( (item = tab[i]) != null) { |
|
1336 |
if (item == k) |
|
1337 |
throw new java.io.StreamCorruptedException(); |
|
1338 |
i = nextKeyIndex(i, len); |
|
1339 |
} |
|
1340 |
tab[i] = k; |
|
1341 |
tab[i + 1] = value; |
|
1342 |
} |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1343 |
|
19208
1e3d351eba80
8022412: Fixed warnings in java.util root, except for HashMap
lagergren
parents:
18280
diff
changeset
|
1344 |
@SuppressWarnings("unchecked") |
18280
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1345 |
@Override |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1346 |
public void forEach(BiConsumer<? super K, ? super V> action) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1347 |
Objects.requireNonNull(action); |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1348 |
int expectedModCount = modCount; |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1349 |
|
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1350 |
Object[] t = table; |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1351 |
for (int index = 0; index < t.length; index += 2) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1352 |
Object k = t[index]; |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1353 |
if (k != null) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1354 |
action.accept((K) unmaskNull(k), (V) t[index + 1]); |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1355 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1356 |
|
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1357 |
if (modCount != expectedModCount) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1358 |
throw new ConcurrentModificationException(); |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1359 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1360 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1361 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1362 |
|
19208
1e3d351eba80
8022412: Fixed warnings in java.util root, except for HashMap
lagergren
parents:
18280
diff
changeset
|
1363 |
@SuppressWarnings("unchecked") |
18280
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1364 |
@Override |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1365 |
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1366 |
Objects.requireNonNull(function); |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1367 |
int expectedModCount = modCount; |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1368 |
|
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1369 |
Object[] t = table; |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1370 |
for (int index = 0; index < t.length; index += 2) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1371 |
Object k = t[index]; |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1372 |
if (k != null) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1373 |
t[index + 1] = function.apply((K) unmaskNull(k), (V) t[index + 1]); |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1374 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1375 |
|
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1376 |
if (modCount != expectedModCount) { |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1377 |
throw new ConcurrentModificationException(); |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1378 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1379 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1380 |
} |
6c3c0ff49eb5
8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap, ConcurrentMap
mduigou
parents:
17168
diff
changeset
|
1381 |
|
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1382 |
/** |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1383 |
* Similar form as array-based Spliterators, but skips blank elements, |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1384 |
* and guestimates size as decreasing by half per split. |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1385 |
*/ |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1386 |
static class IdentityHashMapSpliterator<K,V> { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1387 |
final IdentityHashMap<K,V> map; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1388 |
int index; // current index, modified on advance/split |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1389 |
int fence; // -1 until first use; then one past last index |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1390 |
int est; // size estimate |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1391 |
int expectedModCount; // initialized when fence set |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1392 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1393 |
IdentityHashMapSpliterator(IdentityHashMap<K,V> map, int origin, |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1394 |
int fence, int est, int expectedModCount) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1395 |
this.map = map; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1396 |
this.index = origin; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1397 |
this.fence = fence; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1398 |
this.est = est; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1399 |
this.expectedModCount = expectedModCount; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1400 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1401 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1402 |
final int getFence() { // initialize fence and size on first use |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1403 |
int hi; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1404 |
if ((hi = fence) < 0) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1405 |
est = map.size; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1406 |
expectedModCount = map.modCount; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1407 |
hi = fence = map.table.length; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1408 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1409 |
return hi; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1410 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1411 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1412 |
public final long estimateSize() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1413 |
getFence(); // force init |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1414 |
return (long) est; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1415 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1416 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1417 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1418 |
static final class KeySpliterator<K,V> |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1419 |
extends IdentityHashMapSpliterator<K,V> |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1420 |
implements Spliterator<K> { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1421 |
KeySpliterator(IdentityHashMap<K,V> map, int origin, int fence, int est, |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1422 |
int expectedModCount) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1423 |
super(map, origin, fence, est, expectedModCount); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1424 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1425 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1426 |
public KeySpliterator<K,V> trySplit() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1427 |
int hi = getFence(), lo = index, mid = ((lo + hi) >>> 1) & ~1; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1428 |
return (lo >= mid) ? null : |
22078
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1429 |
new KeySpliterator<>(map, lo, index = mid, est >>>= 1, |
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1430 |
expectedModCount); |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1431 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1432 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1433 |
@SuppressWarnings("unchecked") |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1434 |
public void forEachRemaining(Consumer<? super K> action) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1435 |
if (action == null) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1436 |
throw new NullPointerException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1437 |
int i, hi, mc; Object key; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1438 |
IdentityHashMap<K,V> m; Object[] a; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1439 |
if ((m = map) != null && (a = m.table) != null && |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1440 |
(i = index) >= 0 && (index = hi = getFence()) <= a.length) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1441 |
for (; i < hi; i += 2) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1442 |
if ((key = a[i]) != null) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1443 |
action.accept((K)unmaskNull(key)); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1444 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1445 |
if (m.modCount == expectedModCount) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1446 |
return; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1447 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1448 |
throw new ConcurrentModificationException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1449 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1450 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1451 |
@SuppressWarnings("unchecked") |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1452 |
public boolean tryAdvance(Consumer<? super K> action) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1453 |
if (action == null) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1454 |
throw new NullPointerException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1455 |
Object[] a = map.table; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1456 |
int hi = getFence(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1457 |
while (index < hi) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1458 |
Object key = a[index]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1459 |
index += 2; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1460 |
if (key != null) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1461 |
action.accept((K)unmaskNull(key)); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1462 |
if (map.modCount != expectedModCount) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1463 |
throw new ConcurrentModificationException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1464 |
return true; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1465 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1466 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1467 |
return false; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1468 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1469 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1470 |
public int characteristics() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1471 |
return (fence < 0 || est == map.size ? SIZED : 0) | Spliterator.DISTINCT; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1472 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1473 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1474 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1475 |
static final class ValueSpliterator<K,V> |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1476 |
extends IdentityHashMapSpliterator<K,V> |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1477 |
implements Spliterator<V> { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1478 |
ValueSpliterator(IdentityHashMap<K,V> m, int origin, int fence, int est, |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1479 |
int expectedModCount) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1480 |
super(m, origin, fence, est, expectedModCount); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1481 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1482 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1483 |
public ValueSpliterator<K,V> trySplit() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1484 |
int hi = getFence(), lo = index, mid = ((lo + hi) >>> 1) & ~1; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1485 |
return (lo >= mid) ? null : |
22078
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1486 |
new ValueSpliterator<>(map, lo, index = mid, est >>>= 1, |
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1487 |
expectedModCount); |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1488 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1489 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1490 |
public void forEachRemaining(Consumer<? super V> action) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1491 |
if (action == null) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1492 |
throw new NullPointerException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1493 |
int i, hi, mc; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1494 |
IdentityHashMap<K,V> m; Object[] a; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1495 |
if ((m = map) != null && (a = m.table) != null && |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1496 |
(i = index) >= 0 && (index = hi = getFence()) <= a.length) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1497 |
for (; i < hi; i += 2) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1498 |
if (a[i] != null) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1499 |
@SuppressWarnings("unchecked") V v = (V)a[i+1]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1500 |
action.accept(v); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1501 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1502 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1503 |
if (m.modCount == expectedModCount) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1504 |
return; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1505 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1506 |
throw new ConcurrentModificationException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1507 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1508 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1509 |
public boolean tryAdvance(Consumer<? super V> action) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1510 |
if (action == null) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1511 |
throw new NullPointerException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1512 |
Object[] a = map.table; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1513 |
int hi = getFence(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1514 |
while (index < hi) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1515 |
Object key = a[index]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1516 |
@SuppressWarnings("unchecked") V v = (V)a[index+1]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1517 |
index += 2; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1518 |
if (key != null) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1519 |
action.accept(v); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1520 |
if (map.modCount != expectedModCount) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1521 |
throw new ConcurrentModificationException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1522 |
return true; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1523 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1524 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1525 |
return false; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1526 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1527 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1528 |
public int characteristics() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1529 |
return (fence < 0 || est == map.size ? SIZED : 0); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1530 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1531 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1532 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1533 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1534 |
static final class EntrySpliterator<K,V> |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1535 |
extends IdentityHashMapSpliterator<K,V> |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1536 |
implements Spliterator<Map.Entry<K,V>> { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1537 |
EntrySpliterator(IdentityHashMap<K,V> m, int origin, int fence, int est, |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1538 |
int expectedModCount) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1539 |
super(m, origin, fence, est, expectedModCount); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1540 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1541 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1542 |
public EntrySpliterator<K,V> trySplit() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1543 |
int hi = getFence(), lo = index, mid = ((lo + hi) >>> 1) & ~1; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1544 |
return (lo >= mid) ? null : |
22078
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1545 |
new EntrySpliterator<>(map, lo, index = mid, est >>>= 1, |
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1546 |
expectedModCount); |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1547 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1548 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1549 |
public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1550 |
if (action == null) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1551 |
throw new NullPointerException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1552 |
int i, hi, mc; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1553 |
IdentityHashMap<K,V> m; Object[] a; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1554 |
if ((m = map) != null && (a = m.table) != null && |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1555 |
(i = index) >= 0 && (index = hi = getFence()) <= a.length) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1556 |
for (; i < hi; i += 2) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1557 |
Object key = a[i]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1558 |
if (key != null) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1559 |
@SuppressWarnings("unchecked") K k = |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1560 |
(K)unmaskNull(key); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1561 |
@SuppressWarnings("unchecked") V v = (V)a[i+1]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1562 |
action.accept |
22078
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1563 |
(new AbstractMap.SimpleImmutableEntry<>(k, v)); |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1564 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1565 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1566 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1567 |
if (m.modCount == expectedModCount) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1568 |
return; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1569 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1570 |
throw new ConcurrentModificationException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1571 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1572 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1573 |
public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1574 |
if (action == null) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1575 |
throw new NullPointerException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1576 |
Object[] a = map.table; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1577 |
int hi = getFence(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1578 |
while (index < hi) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1579 |
Object key = a[index]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1580 |
@SuppressWarnings("unchecked") V v = (V)a[index+1]; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1581 |
index += 2; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1582 |
if (key != null) { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1583 |
@SuppressWarnings("unchecked") K k = |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1584 |
(K)unmaskNull(key); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1585 |
action.accept |
22078
bdec5d53e98c
8030851: Update code in java.util to use newer language features
psandoz
parents:
21655
diff
changeset
|
1586 |
(new AbstractMap.SimpleImmutableEntry<>(k, v)); |
17168
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1587 |
if (map.modCount != expectedModCount) |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1588 |
throw new ConcurrentModificationException(); |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1589 |
return true; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1590 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1591 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1592 |
return false; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1593 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1594 |
|
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1595 |
public int characteristics() { |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1596 |
return (fence < 0 || est == map.size ? SIZED : 0) | Spliterator.DISTINCT; |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1597 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1598 |
} |
b7d3500f2516
8011426: java.util collection Spliterator implementations
psandoz
parents:
16042
diff
changeset
|
1599 |
|
2 | 1600 |
} |