ConcurrentMapBasedToDoubleFunctionMemoizer extends ConcurrentMapBasedMemoizer<KEY, Double> implements ToDoubleFunction<INPUT> { @Override public double applyAsDouble(final INPUT value) { final KEY key = keyFunction.apply(value); return computeIfAbsent(key, givenKey -> Double.valueOf(function.applyAsDouble(value))) .doubleValue(); } @SuppressWarnings(CompilerWarnings.NLS)  ConcurrentMapBasedToDoubleFunctionMemoizer(
            final ConcurrentMap<KEY, Double> cache,
            final Function<INPUT, KEY> keyFunction,
            final ToDoubleFunction<INPUT> function); @Override double applyAsDouble(final INPUT value);  }
@Test public void shouldMemoizeFunction() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final ToDoubleFunction<String> function = input -> 123.456D; final Function<String, String> keyFunction = Function.identity(); final ConcurrentMapBasedToDoubleFunctionMemoizer<String, String> memoizer = new ConcurrentMapBasedToDoubleFunctionMemoizer<>( cache, keyFunction, function); memoizer.applyAsDouble("123"); }
@Test public void shouldUseSetCacheKeyAndValue() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final ToDoubleFunction<String> function = input -> 123.456D; final Function<String, String> keyFunction = Function.identity(); final ConcurrentMapBasedToDoubleFunctionMemoizer<String, String> memoizer = new ConcurrentMapBasedToDoubleFunctionMemoizer<>( cache, keyFunction, function); memoizer.applyAsDouble("123"); Assert.assertFalse("Cache is still empty after memoization", memoizer.viewCacheForTest().isEmpty()); Assert.assertEquals("Memoization key does not match expectations", "123", 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 shouldUseCallWrappedFunction() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final ToDoubleFunction<String> function = Mockito.mock(ToDoubleFunction.class); final Function<String, String> keyFunction = Function.identity(); final ConcurrentMapBasedToDoubleFunctionMemoizer<String, String> memoizer = new ConcurrentMapBasedToDoubleFunctionMemoizer<>( cache, keyFunction, function); memoizer.applyAsDouble("123"); Mockito.verify(function).applyAsDouble("123"); }
@Test public void shouldUseReturnFunctionResult() { final ConcurrentMap<String, Double> cache = new ConcurrentHashMap<>(); final ToDoubleFunction<String> function = input -> 123.456D; final Function<String, String> keyFunction = Function.identity(); final ConcurrentMapBasedToDoubleFunctionMemoizer<String, String> memoizer = new ConcurrentMapBasedToDoubleFunctionMemoizer<>( cache, keyFunction, function); Assert.assertEquals(123.456D, memoizer.applyAsDouble("123"), 0.0D); }