@Test public void computeIfAbsent() throws ExecutionException, InterruptedException, IllegalAccessException, NoSuchFieldException { CopyOnWriteLeakyCache<Integer, String> cache = new CopyOnWriteLeakyCache<>(); CompletableFuture[] completableFutures = IntStream.range(0, 10) .mapToObj(threadNumber -> CompletableFuture.runAsync(() -> { for (int i = 0; i < 10_000; i++) { cache.computeIfAbsent(i % 100, ii -> { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } return "v" + ii; }); } })) .toArray(CompletableFuture[]::new); CompletableFuture.allOf(completableFutures).get(); Field cacheField = CopyOnWriteLeakyCache.class.getDeclaredField("map"); cacheField.setAccessible(true); Map<Integer, String> map = (Map<Integer, String>) cacheField.get(cache); for (int i = 0; i < 100; i++) { assertThat(map.get(i)).isEqualTo("v" + i); } }
public V computeIfAbsent(K key, Function<K, V> computeFunction) { V value = map.get(key); if (value != null) { return value; } else { HashMap<K, V> mapCopy = new HashMap<>(map); value = computeFunction.apply(key); mapCopy.put(key, value); map = mapCopy; return value; } }
CopyOnWriteLeakyCache { public V computeIfAbsent(K key, Function<K, V> computeFunction) { V value = map.get(key); if (value != null) { return value; } else { HashMap<K, V> mapCopy = new HashMap<>(map); value = computeFunction.apply(key); mapCopy.put(key, value); map = mapCopy; return value; } } }
CopyOnWriteLeakyCache { public V computeIfAbsent(K key, Function<K, V> computeFunction) { V value = map.get(key); if (value != null) { return value; } else { HashMap<K, V> mapCopy = new HashMap<>(map); value = computeFunction.apply(key); mapCopy.put(key, value); map = mapCopy; return value; } }  }
CopyOnWriteLeakyCache { public V computeIfAbsent(K key, Function<K, V> computeFunction) { V value = map.get(key); if (value != null) { return value; } else { HashMap<K, V> mapCopy = new HashMap<>(map); value = computeFunction.apply(key); mapCopy.put(key, value); map = mapCopy; return value; } }  V computeIfAbsent(K key, Function<K, V> computeFunction); }
CopyOnWriteLeakyCache { public V computeIfAbsent(K key, Function<K, V> computeFunction) { V value = map.get(key); if (value != null) { return value; } else { HashMap<K, V> mapCopy = new HashMap<>(map); value = computeFunction.apply(key); mapCopy.put(key, value); map = mapCopy; return value; } }  V computeIfAbsent(K key, Function<K, V> computeFunction);  }