@Override public V remove(Object key) { if (key == null) { return null; } V priorValue = null; int bucket = bucket(key, _table.length); if (_table[bucket] == null) { // Nothing to do } else if (_table[bucket] instanceof ChainedEntry) { // The front of the bucket is a ChainedEntry, so we need to walk the chain and splice out the // link ChainedEntry<V> previousLink = null; ChainedEntry<V> currentLink = (ChainedEntry<V>) _table[bucket]; while (true) { if (keyMatches(key, currentLink._entry)) { // We have a match, so splice out the link priorValue = currentLink._entry; if (previousLink == null) { // There's no prior link, so pull the next object directly into the table _table[bucket] = currentLink._next; } else { // There's a prior link, so just splice out the current one previousLink._next = currentLink._next; } break; } else if (currentLink._next instanceof ChainedEntry) { // Just previousLink = currentLink; currentLink = (ChainedEntry<V>) currentLink._next; } else { // The next link in the chain is a direct entry. If it matches the key we're looking // for, we need to remove the current link, as it's no longer necessary, and set // the _next pointer (if any) of the prior link to point directly to the current link's // entry if (keyMatches(key, (V) currentLink._next)) { priorValue = (V) currentLink._next; if (previousLink == null) { _table[bucket] = currentLink._entry; } else { previousLink._next = currentLink._entry; } } break; } } } else { // The entry is directly in _table, so just null it out priorValue = (V) _table[bucket]; _table[bucket] = null; } if (priorValue != null) { _size--; } return priorValue; }
public V putImpl(K key, V value, Object[] table, boolean resizeIfNecessary) { if (key == null) { throw new IllegalArgumentException( "Cannot add a value with a null key to a DerivedKeyHashMap"); } if (value == null) { throw new IllegalArgumentException("Cannot add a null value to a DerivedKeyHashMap"); } V priorValue = null; int bucket = bucket(key, table.length); if (table[bucket] == null) { table[bucket] = value; } else if (table[bucket] instanceof ChainedEntry) { // The front of the bucket is a ChainedEntry, so we need to walk the chain ChainedEntry<V> lastChain = (ChainedEntry<V>) table[bucket]; while (true) { if (keyMatches(key, lastChain._entry)) { // If the entry of the chain directly matches our value's key, then update it in place priorValue = lastChain._entry; lastChain._entry = value; break; } else if (lastChain._next instanceof ChainedEntry) { // If the entry doesn't match and the next object is another chain entry, keep walking the // chain lastChain = (ChainedEntry<V>) lastChain._next; } else { // If the next link in the chain isn't another chain link, either update the value pointer // directly, // if it matches this value's key, or if (keyMatches(key, (V) lastChain._next)) { priorValue = (V) lastChain._next; lastChain._next = value; } else { ChainedEntry<V> newChain = new ChainedEntry<V>((V) lastChain._next, value); lastChain._next = newChain; } break; } } } else { // The entry is directly in _table, so if the existing value there matches this key, overwrite // it // Otherwise, chain the new value in if (keyMatches(key, (V) table[bucket])) { priorValue = (V) table[bucket]; table[bucket] = value; } else { table[bucket] = new ChainedEntry<V>((V) table[bucket], value); } } return priorValue; }