ConcurrentMapBasedToDoubleBiFunctionMemoizer extends ConcurrentMapBasedMemoizer<KEY, Double> implements ToDoubleBiFunction<FIRST, SECOND> { @Override public double applyAsDouble(final FIRST t, final SECOND u) { final KEY key = keyFunction.apply(t, u); return computeIfAbsent(key, givenKey -> Double.valueOf(function.applyAsDouble(t, u))).doubleValue(); } @SuppressWarnings(CompilerWarnings.NLS)  ConcurrentMapBasedToDoubleBiFunctionMemoizer(
            final ConcurrentMap<KEY, Double> cache,
            final BiFunction<FIRST, SECOND, KEY> keyFunction,
            final ToDoubleBiFunction<FIRST, SECOND> function); @Override double applyAsDouble(final FIRST t, final SECOND u);  }
@Test public void shouldMemoizeBiFunction() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToDoubleBiFunction<String, String> biFunction = (a, b) -> 123.456D; final ConcurrentMapBasedToDoubleBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToDoubleBiFunctionMemoizer<>( cache, keyFunction, biFunction); memoizer.applyAsDouble("123.456", "789.123"); }
@Test public void shouldUseSetCacheKeyAndValue() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToDoubleBiFunction<String, String> biFunction = (a, b) -> 123.456D; final ConcurrentMapBasedToDoubleBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToDoubleBiFunctionMemoizer<>( cache, keyFunction, biFunction); memoizer.applyAsDouble("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", 123.456D, memoizer.viewCacheForTest().values().iterator().next().doubleValue(), 0.0D); }
@Test @SuppressWarnings(CompilerWarnings.UNCHECKED) public void shouldUseCallWrappedBiFunction() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToDoubleBiFunction<String, String> biFunction = Mockito.mock(ToDoubleBiFunction.class); final ConcurrentMapBasedToDoubleBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToDoubleBiFunctionMemoizer<>( cache, keyFunction, biFunction); memoizer.applyAsDouble("123.456", "789.123"); Mockito.verify(biFunction).applyAsDouble("123.456", "789.123"); }
@Test public void shouldUseReturnBiFunctionResult() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final BiFunction<String, String, String> keyFunction = (a, b) -> "key"; final ToDoubleBiFunction<String, String> biFunction = (a, b) -> 123.456D; final ConcurrentMapBasedToDoubleBiFunctionMemoizer<String, String, String> memoizer = new ConcurrentMapBasedToDoubleBiFunctionMemoizer<>( cache, keyFunction, biFunction); Assert.assertEquals(123.456D, memoizer.applyAsDouble("123.456", "789.123"), 0.0D); }