ReferenceCountedHashMap extends HashMap<K, V> { public synchronized V remove(Object key) { if (!super.containsKey(key)) { return null; } Integer currentCount = this.updateReference(key, -1); if (currentCount <= 0) { V value = super.remove(key); if (cleanerCallback != null) { cleanerCallback.call(value); } return value; } else { return super.get(key); } } ReferenceCountedHashMap();  ReferenceCountedHashMap(Callable<V> cleanerCallable); synchronized V put(K key, V value); synchronized V remove(Object key); void clear(); Object clone(); void putAll(Map<? extends K, ? extends V> m);  }
@Test public void test_emptyRemoveReturnsNull() { Map<String, Integer> testMap = new ReferenceCountedHashMap<>(); Assert.assertNull(testMap.remove(KEYS[0])); }
@Test public void test_emptyDoesntCallCallback() { final int[] accessor = {999}; Map<String, Integer> testMap = new ReferenceCountedHashMap<>( new Callable<Integer>() { @Override public void call(Integer input) { accessor[0] = input; } }); Assert.assertNull(testMap.remove(KEYS[0])); Assert.assertEquals(accessor[0], 999); }