ConcurrentMapBasedToLongBiFunctionMemoizer extends ConcurrentMapBasedMemoizer<KEY, Long> implements ToLongBiFunction<FIRST, SECOND> { @Override public long applyAsLong(final FIRST t, final SECOND u) { final KEY key = keyFunction.apply(t, u); return computeIfAbsent(key, givenKey -> Long.valueOf(function.applyAsLong(t, u))).longValue(); } @SuppressWarnings(CompilerWarnings.NLS)  ConcurrentMapBasedToLongBiFunctionMemoizer(
            final ConcurrentMap<KEY, Long> cache,
            final BiFunction<FIRST, SECOND, KEY> keyFunction,
            final ToLongBiFunction<FIRST, SECOND> function); @Override long applyAsLong(final FIRST t, final SECOND u);  }
@Test public void shouldMemoizeBiFunction() { final ConcurrentMap<String, Long> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToLongBiFunction<String, String> biFunction = (a, b) -> 123L; final ConcurrentMapBasedToLongBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToLongBiFunctionMemoizer<>( cache, keyFunction, biFunction); memoizer.applyAsLong("123.456", "789.123"); }
@Test public void shouldUseSetCacheKeyAndValue() { final ConcurrentMap<String, Long> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToLongBiFunction<String, String> biFunction = (a, b) -> 123L; final ConcurrentMapBasedToLongBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToLongBiFunctionMemoizer<>( cache, keyFunction, biFunction); memoizer.applyAsLong("123.456", "789.123"); Assert.assertFalse("Cache is still empty after memoization", memoizer.viewCacheForTest().isEmpty()); Assert.assertEquals("Memoization key does not match expectations", "key", memoizer.viewCacheForTest().keySet().iterator().next()); Assert.assertEquals("Memoization value does not match expectations", 123L, memoizer.viewCacheForTest().values().iterator().next().longValue()); }
@Test @SuppressWarnings(CompilerWarnings.UNCHECKED) public void shouldUseCallWrappedBiFunction() { final ConcurrentMap<String, Long> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToLongBiFunction<String, String> biFunction = Mockito.mock(ToLongBiFunction.class); final ConcurrentMapBasedToLongBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToLongBiFunctionMemoizer<>( cache, keyFunction, biFunction); memoizer.applyAsLong("123.456", "789.123"); Mockito.verify(biFunction).applyAsLong("123.456", "789.123"); }
@Test public void shouldUseReturnBiFunctionResult() { final ConcurrentMap<String, Long> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToLongBiFunction<String, String> biFunction = (a, b) -> 123L; final ConcurrentMapBasedToLongBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToLongBiFunctionMemoizer<>( cache, keyFunction, biFunction); Assert.assertEquals(123L, memoizer.applyAsLong("123.456", "789.123")); }