ConcurrentMapBasedBiConsumerMemoizer extends ConcurrentMapBasedMemoizer<KEY, KEY> implements BiConsumer<FIRST, SECOND> { @Override public void accept(final FIRST first, final SECOND second) { final KEY key = keyFunction.apply(first, second); computeIfAbsent(key, givenKey -> { biConsumer.accept(first, second); return givenKey; }); } @SuppressWarnings(CompilerWarnings.NLS)  ConcurrentMapBasedBiConsumerMemoizer(
            final ConcurrentMap<KEY, KEY> cache,
            final BiFunction<FIRST, SECOND, KEY> keyFunction,
            final BiConsumer<FIRST, SECOND> biConsumer); @Override void accept(final FIRST first, final SECOND second);  }
@Test public void shouldMemoizeBiConsumer() { final ConcurrentMap<String, String> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (first, second) -> first + second; final BiConsumer<String, String> biConsumer = (first, second) -> System.out.println(first + second); final ConcurrentMapBasedBiConsumerMemoizer<String, String, String> memoizer = new ConcurrentMapBasedBiConsumerMemoizer<>( cache, keyFunction, biConsumer); memoizer.accept("first", "second"); }
@Test public void shouldUseSetCacheKeyAndValue() { final ConcurrentMap<String, String> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (first, second) -> first + second; final BiConsumer<String, String> biConsumer = (first, second) -> System.out.println(first + second); final ConcurrentMapBasedBiConsumerMemoizer<String, String, String> memoizer = new ConcurrentMapBasedBiConsumerMemoizer<>( cache, keyFunction, biConsumer); memoizer.accept("first", "second"); Assert.assertFalse("Cache is still empty after memoization", memoizer.viewCacheForTest().isEmpty()); Assert.assertEquals("Memoization key does not match expectations", "firstsecond", memoizer.viewCacheForTest().keySet().iterator().next()); Assert.assertEquals("Memoization value does not match expectations", "firstsecond", memoizer.viewCacheForTest().values().iterator().next()); }
@Test @SuppressWarnings(CompilerWarnings.UNCHECKED) public void shouldUseCallWrappedBiConsumer() { final ConcurrentMap<String, String> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (first, second) -> first + second; final BiConsumer<String, String> biConsumer = Mockito.mock(BiConsumer.class); final ConcurrentMapBasedBiConsumerMemoizer<String, String, String> memoizer = new ConcurrentMapBasedBiConsumerMemoizer<>( cache, keyFunction, biConsumer); memoizer.accept("first", "second"); Mockito.verify(biConsumer).accept("first", "second"); }