219 *
220 * @param initialCapacity the initial capacity
221 * @param loadFactor the load factor
222 * @param accessOrder the ordering mode - <tt>true</tt> for
223 * access-order, <tt>false</tt> for insertion-order
224 * @throws IllegalArgumentException if the initial capacity is negative
225 * or the load factor is nonpositive
226 */
227 public LinkedHashMap(int initialCapacity,
228 float loadFactor,
229 boolean accessOrder) {
230 super(initialCapacity, loadFactor);
231 this.accessOrder = accessOrder;
232 }
233
234 /**
235 * Called by superclass constructors and pseudoconstructors (clone,
236 * readObject) before any entries are inserted into the map. Initializes
237 * the chain.
238 */
239 void init() {
240 header = new Entry<>(-1, null, null, null);
241 header.before = header.after = header;
242 }
243
244 /**
245 * Transfers all entries to new table array. This method is called
246 * by superclass resize. It is overridden for performance, as it is
247 * faster to iterate using our linked list.
248 */
249 void transfer(HashMap.Entry[] newTable) {
250 int newCapacity = newTable.length;
251 for (Entry<K,V> e = header.after; e != header; e = e.after) {
252 int index = indexFor(e.hash, newCapacity);
253 e.next = newTable[index];
254 newTable[index] = e;
255 }
256 }
257
258
259 /**
260 * Returns <tt>true</tt> if this map maps one or more keys to the
261 * specified value.
262 *
263 * @param value value whose presence in this map is to be tested
264 * @return <tt>true</tt> if this map maps one or more keys to the
265 * specified value
266 */
267 public boolean containsValue(Object value) {
268 // Overridden to take advantage of faster iterator
269 if (value==null) {
270 for (Entry e = header.after; e != header; e = e.after)
271 if (e.value==null)
403
404 private class ValueIterator extends LinkedHashIterator<V> {
405 public V next() { return nextEntry().value; }
406 }
407
408 private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
409 public Map.Entry<K,V> next() { return nextEntry(); }
410 }
411
412 // These Overrides alter the behavior of superclass view iterator() methods
413 Iterator<K> newKeyIterator() { return new KeyIterator(); }
414 Iterator<V> newValueIterator() { return new ValueIterator(); }
415 Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
416
417 /**
418 * This override alters behavior of superclass put method. It causes newly
419 * allocated entry to get inserted at the end of the linked list and
420 * removes the eldest entry if appropriate.
421 */
422 void addEntry(int hash, K key, V value, int bucketIndex) {
423 createEntry(hash, key, value, bucketIndex);
424
425 // Remove eldest entry if instructed, else grow capacity if appropriate
426 Entry<K,V> eldest = header.after;
427 if (removeEldestEntry(eldest)) {
428 removeEntryForKey(eldest.key);
429 } else {
430 if (size >= threshold)
431 resize(2 * table.length);
432 }
433 }
434
435 /**
436 * This override differs from addEntry in that it doesn't resize the
437 * table or remove the eldest entry.
438 */
439 void createEntry(int hash, K key, V value, int bucketIndex) {
440 HashMap.Entry<K,V> old = table[bucketIndex];
441 Entry<K,V> e = new Entry<>(hash, key, value, old);
442 table[bucketIndex] = e;
443 e.addBefore(header);
444 size++;
445 }
446
447 /**
448 * Returns <tt>true</tt> if this map should remove its eldest entry.
449 * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
450 * inserting a new entry into the map. It provides the implementor
451 * with the opportunity to remove the eldest entry each time a new one
|
219 *
220 * @param initialCapacity the initial capacity
221 * @param loadFactor the load factor
222 * @param accessOrder the ordering mode - <tt>true</tt> for
223 * access-order, <tt>false</tt> for insertion-order
224 * @throws IllegalArgumentException if the initial capacity is negative
225 * or the load factor is nonpositive
226 */
227 public LinkedHashMap(int initialCapacity,
228 float loadFactor,
229 boolean accessOrder) {
230 super(initialCapacity, loadFactor);
231 this.accessOrder = accessOrder;
232 }
233
234 /**
235 * Called by superclass constructors and pseudoconstructors (clone,
236 * readObject) before any entries are inserted into the map. Initializes
237 * the chain.
238 */
239 @Override
240 void init() {
241 header = new Entry<>(-1, null, null, null);
242 header.before = header.after = header;
243 }
244
245 /**
246 * Transfers all entries to new table array. This method is called
247 * by superclass resize. It is overridden for performance, as it is
248 * faster to iterate using our linked list.
249 */
250 @Override
251 void transfer(HashMap.Entry[] newTable, boolean rehash) {
252 int newCapacity = newTable.length;
253 for (Entry<K,V> e = header.after; e != header; e = e.after) {
254 if (rehash)
255 e.hash = (e.key == null) ? 0 : hash(e.key);
256 int index = indexFor(e.hash, newCapacity);
257 e.next = newTable[index];
258 newTable[index] = e;
259 }
260 }
261
262
263 /**
264 * Returns <tt>true</tt> if this map maps one or more keys to the
265 * specified value.
266 *
267 * @param value value whose presence in this map is to be tested
268 * @return <tt>true</tt> if this map maps one or more keys to the
269 * specified value
270 */
271 public boolean containsValue(Object value) {
272 // Overridden to take advantage of faster iterator
273 if (value==null) {
274 for (Entry e = header.after; e != header; e = e.after)
275 if (e.value==null)
407
408 private class ValueIterator extends LinkedHashIterator<V> {
409 public V next() { return nextEntry().value; }
410 }
411
412 private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
413 public Map.Entry<K,V> next() { return nextEntry(); }
414 }
415
416 // These Overrides alter the behavior of superclass view iterator() methods
417 Iterator<K> newKeyIterator() { return new KeyIterator(); }
418 Iterator<V> newValueIterator() { return new ValueIterator(); }
419 Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
420
421 /**
422 * This override alters behavior of superclass put method. It causes newly
423 * allocated entry to get inserted at the end of the linked list and
424 * removes the eldest entry if appropriate.
425 */
426 void addEntry(int hash, K key, V value, int bucketIndex) {
427 super.addEntry(hash, key, value, bucketIndex);
428
429 // Remove eldest entry if instructed
430 Entry<K,V> eldest = header.after;
431 if (removeEldestEntry(eldest)) {
432 removeEntryForKey(eldest.key);
433 }
434 }
435
436 /**
437 * This override differs from addEntry in that it doesn't resize the
438 * table or remove the eldest entry.
439 */
440 void createEntry(int hash, K key, V value, int bucketIndex) {
441 HashMap.Entry<K,V> old = table[bucketIndex];
442 Entry<K,V> e = new Entry<>(hash, key, value, old);
443 table[bucketIndex] = e;
444 e.addBefore(header);
445 size++;
446 }
447
448 /**
449 * Returns <tt>true</tt> if this map should remove its eldest entry.
450 * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
451 * inserting a new entry into the map. It provides the implementor
452 * with the opportunity to remove the eldest entry each time a new one
|