public void remove() { if (!iterator) throw new UnsupportedOperationException(); if (lastReturned == null) throw new IllegalStateException("Hashtable Enumerator"); if (modCount != expectedModCount) throw new ConcurrentModificationException(); synchronized (Hashtable.this) { Entry<?, ?>[] tab = Hashtable.this.table; int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K, V> e = (Entry<K, V>) tab[index]; for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) { if (e == lastReturned) { if (prev == null) tab[index] = e.next; else prev.next = e.next; expectedModCount++; lastReturned = null; Hashtable.this.modCount++; Hashtable.this.count--; return; } } throw new ConcurrentModificationException(); } }
/** * {@inheritDoc} * * <p>This method will, on a best-effort basis, throw a {@link * java.util.ConcurrentModificationException} if the remapping function modified this map during * computation. * * @throws ConcurrentModificationException if it is detected that the remapping function modified * this map */ @Override public synchronized V computeIfPresent( K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { Objects.requireNonNull(remappingFunction); Entry<?, ?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K, V> e = (Entry<K, V>) tab[index]; for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.key.equals(key)) { int mc = modCount; V newValue = remappingFunction.apply(key, e.value); if (mc != modCount) { throw new ConcurrentModificationException(); } if (newValue == null) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } modCount = mc + 1; count--; } else { e.value = newValue; } return newValue; } } return null; }
/** * Increases the capacity of and internally reorganizes this hashtable, in order to accommodate * and access its entries more efficiently. This method is called automatically when the number of * keys in the hashtable exceeds this hashtable's capacity and load factor. */ @SuppressWarnings("unchecked") protected void rehash() { int oldCapacity = table.length; Entry<?, ?>[] oldMap = table; // overflow-conscious code int newCapacity = (oldCapacity << 1) + 1; if (newCapacity - MAX_ARRAY_SIZE > 0) { if (oldCapacity == MAX_ARRAY_SIZE) // Keep running with MAX_ARRAY_SIZE buckets return; newCapacity = MAX_ARRAY_SIZE; } Entry<?, ?>[] newMap = new Entry<?, ?>[newCapacity]; modCount++; threshold = (int) Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1); table = newMap; for (int i = oldCapacity; i-- > 0; ) { for (Entry<K, V> old = (Entry<K, V>) oldMap[i]; old != null; ) { Entry<K, V> e = old; old = old.next; int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = (Entry<K, V>) newMap[index]; newMap[index] = e; } } }
/** Special version of remove for EntrySet using {@code Map.Entry.equals()} for matching. */ final Entry<K, V> removeMapping(Object o) { if (!(o instanceof Map.Entry)) return null; Map.Entry<K, V> entry = (Map.Entry<K, V>) o; Object key = entry.getKey(); int hash = (key == null) ? 0 : hash(key); int i = indexFor(hash, table.length); Entry<K, V> prev = table[i]; Entry<K, V> e = prev; while (e != null) { Entry<K, V> next = e.next; if (e.hash == hash && e.equals(entry)) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; }
/** Transfers all entries from current table to newTable. */ void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; for (Entry<K, V> e : table) { while (null != e) { Entry<K, V> next = e.next; if (rehash) { e.hash = null == e.key ? 0 : hash(e.key); } int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } } }
/** * Removes the key (and its corresponding value) from this hashtable. This method does nothing if * the key is not in the hashtable. * * @param key the key that needs to be removed * @return the value to which the key had been mapped in this hashtable, or <code>null</code> if * the key did not have a mapping * @throws NullPointerException if the key is <code>null</code> */ public synchronized V remove(Object key) { Entry tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { modCount++; if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; V oldValue = e.value; e.value = null; return oldValue; } } return null; }
public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K, V> entry = (Map.Entry<K, V>) o; K key = entry.getKey(); Entry[] tab = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.equals(entry)) { modCount++; if (prev != null) prev.next = e.next; else tab[index] = e.next; count--; e.value = null; return true; } } return false; }
/** * Removes the key (and its corresponding value) from this hashtable. This method does nothing if * the key is not in the hashtable. * * @param key the key that needs to be removed * @return the value to which the key had been mapped in this hashtable, or {@code null} if the * key did not have a mapping * @throws NullPointerException if the key is {@code null} */ public synchronized V remove(Object key) { Entry<?, ?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K, V> e = (Entry<K, V>) tab[index]; for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } modCount++; count--; V oldValue = e.value; e.value = null; return oldValue; } } return null; }
public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o; Object key = entry.getKey(); Entry<?, ?>[] tab = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K, V> e = (Entry<K, V>) tab[index]; for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && e.equals(entry)) { if (prev != null) prev.next = e.next; else tab[index] = e.next; e.value = null; // clear for gc. modCount++; count--; return true; } } return false; }
/** * Removes and returns the entry associated with the specified key in the HashMap. Returns null if * the HashMap contains no mapping for this key. */ final Entry<K, V> removeEntryForKey(Object key) { int hash = (key == null) ? 0 : hash(key); int i = indexFor(hash, table.length); Entry<K, V> prev = table[i]; Entry<K, V> e = prev; while (e != null) { Entry<K, V> next = e.next; Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; }
@Override public synchronized boolean remove(Object key, Object value) { Objects.requireNonNull(value); Entry<?, ?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K, V> e = (Entry<K, V>) tab[index]; for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } e.value = null; // clear for gc modCount++; count--; return true; } } return false; }