I tried to extend the HashMap
class to implement a custom remove()
method, like this:
@SuppressWarnings("serial")
private final class EntryHashMap<K, E> extends HashMap<K, E> {
@Override
public E remove(Object key) {
rowKeyMap.remove(key);
colKeyMap.remove(key);
return super.remove(key);
}
}
It all works well if remove()
is invoked directly, but when an iterator is used to remove the entry, the remove()
method of HashMap
is invoked instead of the above overriden remove()
method:
public boolean selectiveRemove(Object key) {
boolean result = false;
Iterator<Entry<K, E>> it = entrySet().iterator();
while( it.hasNext() ) {
Entry<K, E> entry = it.next();
K rowKey = entry.getKey();
if( Utils.equals(key, rowKey) ) {
it.remove(); // <<<<< this does not invoke the new `remove()`
result = true;
}
}
return result;
}
After looking at the source code for HashMap
in the entry iterator I see:
private abstract class HashIterator {
. . .
public boolean hasNext() {
. . .
}
HashMapEntry<K, V> nextEntry() {
. . .
}
public void remove() {
if (lastEntryReturned == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
HashMap.this.remove(lastEntryReturned.key); // <<< Hard coded call to HashMap's remove()
lastEntryReturned = null;
expectedModCount = modCount;
}
}
private final class EntryIterator extends HashIterator
implements Iterator<Entry<K, V>> {
public Entry<K, V> next() { return nextEntry(); }
}
Extended HashMap
classes do not have access to all private fields, so I cannot just modify the iterator, I would have to rewrite a lot of code to get my own iterator override that iterator.
Is there a way to completely override remove()
so it gets called in every situation where HashMap.remove()
was called?