CE-938 update memoization to say if it should store null values or not

This commit is contained in:
2024-05-19 20:21:03 -05:00
parent be69836b5b
commit 485bc618e0
2 changed files with 127 additions and 2 deletions

View File

@ -43,8 +43,9 @@ public class Memoization<K, V>
private final Map<K, MemoizedResult<V>> map = Collections.synchronizedMap(new LinkedHashMap<>());
private Duration timeout = Duration.ofSeconds(600);
private Integer maxSize = 1000;
private Duration timeout = Duration.ofSeconds(600);
private Integer maxSize = 1000;
private boolean mayStoreNullValues = true;
@ -58,6 +59,40 @@ public class Memoization<K, V>
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public Memoization(Integer maxSize)
{
this.maxSize = maxSize;
}
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public Memoization(Duration timeout)
{
this.timeout = timeout;
}
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public Memoization(Duration timeout, Integer maxSize)
{
this.timeout = timeout;
this.maxSize = maxSize;
}
/*******************************************************************************
** Get the memoized Value for a given input Key - computing it if it wasn't previously
** memoized (or expired).
@ -153,6 +188,14 @@ public class Memoization<K, V>
*******************************************************************************/
public void storeResult(K key, V value)
{
//////////////////////////////////////////////////////////////////////////////////////////
// if the value is null, and we're not supposed to store nulls, then return w/o storing //
//////////////////////////////////////////////////////////////////////////////////////////
if(value == null && !mayStoreNullValues)
{
return;
}
map.put(key, new MemoizedResult<>(value));
//////////////////////////////////////
@ -277,4 +320,35 @@ public class Memoization<K, V>
return (this);
}
/*******************************************************************************
** Getter for mayStoreNullValues
*******************************************************************************/
public boolean getMayStoreNullValues()
{
return (this.mayStoreNullValues);
}
/*******************************************************************************
** Setter for mayStoreNullValues
*******************************************************************************/
public void setMayStoreNullValues(boolean mayStoreNullValues)
{
this.mayStoreNullValues = mayStoreNullValues;
}
/*******************************************************************************
** Fluent setter for mayStoreNullValues
*******************************************************************************/
public Memoization<K, V> withMayStoreNullValues(boolean mayStoreNullValues)
{
this.mayStoreNullValues = mayStoreNullValues;
return (this);
}
}

View File

@ -119,6 +119,57 @@ class MemoizationTest extends BaseTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testMayNotStoreNull()
{
Memoization<String, String> memoization = new Memoization<>();
memoization.setMayStoreNullValues(false);
AtomicInteger callCounter = new AtomicInteger();
callCounter.set(0);
UnsafeFunction<String, String, Exception> supplier = name ->
{
callCounter.getAndIncrement();
if(name.equals("throw"))
{
throw (new Exception("You asked me to throw"));
}
else if(name.equals("null"))
{
return (null);
}
else
{
return (name);
}
};
assertThat(memoization.getResult("null", supplier)).isEmpty();
assertEquals(1, callCounter.get());
assertThat(memoization.getResult("null", supplier)).isEmpty();
assertEquals(2, callCounter.get()); // should re-run the supplier, incrementing the counter
assertThat(memoization.getResult("throw", supplier)).isEmpty();
assertEquals(3, callCounter.get());
assertThat(memoization.getResult("throw", supplier)).isEmpty();
assertEquals(4, callCounter.get()); // should re-run the supplier, incrementing the counter
//noinspection AssertBetweenInconvertibleTypes
assertThat(memoization.getResult("foo", supplier)).isPresent().get().isEqualTo("foo");
assertEquals(5, callCounter.get());
//noinspection AssertBetweenInconvertibleTypes
assertThat(memoization.getResult("foo", supplier)).isPresent().get().isEqualTo("foo");
assertEquals(5, callCounter.get()); // should NOT re-run the supplier, NOT incrementing the counter
}
/*******************************************************************************
**
*******************************************************************************/