ConcurrentMapBasedDoubleFunctionMemoizer extends ConcurrentMapBasedMemoizer<KEY, OUTPUT> implements DoubleFunction<OUTPUT> { @Override public OUTPUT apply(final double value) { final KEY key = keyFunction.apply(value); return computeIfAbsent(key, givenKey -> function.apply(value)); } @SuppressWarnings(CompilerWarnings.NLS)  ConcurrentMapBasedDoubleFunctionMemoizer(
            final ConcurrentMap<KEY, OUTPUT> cache,
            final DoubleFunction<KEY> keyFunction,
            final DoubleFunction<OUTPUT> function); @Override OUTPUT apply(final double value);  }
@Test public void shouldMemoizeFunctionCall() { final ConcurrentMap<String, String> cache = new ConcurrentHashMap<>(); final DoubleFunction<String> function = input -> "output"; final DoubleFunction<String> keyFunction = input -> "key"; final ConcurrentMapBasedDoubleFunctionMemoizer<String, String> memoizer = new ConcurrentMapBasedDoubleFunctionMemoizer<>( cache, keyFunction, function); Assert.assertEquals("Memoized value does not match expectations", "output", memoizer.apply(123)); }