Cache implements Retriever<K,V> { @Override public V get(K key) throws TasteException { V value; synchronized (cache) { value = cache.get(key); } if (value == null) { return getAndCacheValue(key); } return value == NULL ? null : value; } Cache(Retriever<? super K,? extends V> retriever);  Cache(Retriever<? super K,? extends V> retriever, int maxEntries); @Override V get(K key); void remove(K key); void removeKeysMatching(MatchPredicate<K> predicate); void removeValueMatching(MatchPredicate<V> predicate); void clear(); @Override String toString();  }
@Test public void testLotsOfGets() throws TasteException { Retriever<Object,Object> retriever = new IdentityRetriever(); Cache<Object,Object> cache = new Cache<>(retriever, 1000); for (int i = 0; i < 1000000; i++) { assertEquals(i, cache.get(i)); } }