public void remove() { if (lastReturned == null) { throw new IllegalStateException(); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } WeakEntry[] copyOfEntries = IdentityWeakHashMap.this.entries; int index = (lastReturned.hash & 0x7FFFFFFF) % copyOfEntries.length; for (WeakEntry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) { if (e == lastReturned) { modCount++; expectedModCount++; if (prev == null) { copyOfEntries[index] = e.next; } else { prev.next = e.next; } count--; lastReturned = null; return; } } throw new ConcurrentModificationException(); }
protected boolean removeEntry(WeakEntry o, boolean userModification) { WeakEntry[] copyOfEntries = entries; int index = (o.hash & 0x7FFFFFFF) % copyOfEntries.length; for (WeakEntry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) { if (e == o) { // if this method was called as a result of a user action, // increment the modification count // this method is also called by our cleanup code and // that code should not cause a concurrent modification // exception if (userModification) { modCount++; } if (prev != null) { prev.next = e.next; } else { copyOfEntries[index] = e.next; } count--; e.value = null; e.next = null; return true; } } return false; }
/** * Associate the given object with the given key in this <tt>IdentityWeakHashMap</tt>, replacing * any existing mapping. * * @param key key to map to given object. * @param obj object to be associated with key. * @return the previous object for key or <tt>null</tt> if this <tt>IdentityWeakHashMap</tt> did * not have one. * @throws <tt>NullPointerException</tt> if obj is null</tt>. */ public V put(K key, V obj) { if (obj == null || key == null) { throw new IllegalArgumentException( ExceptionLocalization.buildMessage("null_not_supported_identityweakhashmap")); } cleanUp(); WeakEntry[] copyOfEntries = entries; int hash = System.identityHashCode(key); int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; for (WeakEntry e = copyOfEntries[index]; e != null; e = e.next) { if (e.key.get() == key) { EntryReference<V> old = e.value; if (key == obj) { e.value = e.key; } else { e.value = new HardEntryReference<V>(obj); } return old.get(); } } modCount++; if (count >= threshold) { rehash(); copyOfEntries = entries; index = (hash & 0x7FFFFFFF) % copyOfEntries.length; } WeakEntry<K, V> e = new WeakEntry<K, V>(hash, key, obj, copyOfEntries[index], referenceQueue); copyOfEntries[index] = e; count++; return null; }
/** * INTERNAL: Re-builds the internal array of Entry's with a larger capacity. This method is called * automatically when the number of objects in this IdentityWeakHashMap exceeds its current * threshold. */ private void rehash() { int oldCapacity = entries.length; WeakEntry[] oldEntries = entries; int newCapacity = (oldCapacity * 2) + 1; WeakEntry[] newEntries = new WeakEntry[newCapacity]; modCount++; threshold = (int) (newCapacity * loadFactor); entries = newEntries; for (int i = oldCapacity; i-- > 0; ) { for (WeakEntry old = oldEntries[i]; old != null; ) { WeakEntry e = old; old = old.next; int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = newEntries[index]; newEntries[index] = e; } } }
/** * Removes the mapping (key and its corresponding value) from this <tt>IdentityWeakHashMap</tt>, * if present. * * @param key key whose mapping is to be removed from the map. * @return the previous object for key or <tt>null</tt> if this <tt>IdentityWeakHashMap</tt> did * not have one. */ public V remove(Object key) { if (key == null) return null; cleanUp(); WeakEntry[] copyOfEntries = entries; int hash = System.identityHashCode(key); int index = (hash & 0x7FFFFFFF) % copyOfEntries.length; for (WeakEntry e = copyOfEntries[index], prev = null; e != null; prev = e, e = e.next) { if (e.key.get() == key) { if (prev != null) { prev.next = e.next; } else { copyOfEntries[index] = e.next; } count--; return (V) e.value.get(); } } return null; }
protected Object clone(ReferenceQueue refQueue) { WeakEntry current = this; WeakEntry root = new WeakEntry(current.hash, current.key.get(), current.value.get(), null, refQueue); WeakEntry currentClone = root; while (current.next != null) { currentClone.next = new WeakEntry( current.next.hash, current.next.key.get(), current.next.value.get(), null, refQueue); current = current.next; currentClone = currentClone.next; } return root; }