This method, as I know, memorizes (caches) the value of supplier that passed as the parameter. As I understand It behaves like singleton pattern. Can anyone explain how it works?
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier)
{
final List<T> memoryList= new ArrayList<>();
return () -> {
if (memoryList.isEmpty()) {
memoryList.add(valueSupplier.get());
}
return memoryList.get(0);
};
}
Usage like this:
Supplier<SomeClass> cachedValue = memoize(() -> someClassObject.getSomeValueToBeCached());
cachedValue.get().doMethod();
Ok, so let's rewrite the code in small steps towards more old-style, verbose Java. Maybe that makes it simpler to understand.
First step: get rid of the lambda:
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier)
{
final List<T> memoryList= new ArrayList<>();
return new Supplier<T>() {
@Override
public T get() {
if (memoryList.isEmpty()) {
memoryList.add(valueSupplier.get());
}
return memoryList.get(0);
}
};
}
Next step: extract the anonymous inner class into a standalone class.
While the anonymous class had access to the local variables of its containing method (memoryList
), a "normal" class has not, so we're moving the list into the caching supplier.
class CachingSupplier<T> implements Supplier<T> {
final List<T> memoryList= new ArrayList<>();
private Supplier<T> originalSupplier;
public CachingSupplier(Supplier<T> originalSupplier) {
this.originalSupplier = originalSupplier;
}
@Override
public T get() {
if (memoryList.isEmpty()) {
memoryList.add(originalSupplier.get());
}
return memoryList.get(0);
}
}
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier) {
return new CachingSupplier<>(valueSupplier);
}
Finally, let's replace the ArrayList by a simple reference.
class CachingSupplier<T> implements Supplier<T> {
private T cachedValue;
private Supplier<T> originalSupplier;
public CachingSupplier(Supplier<T> originalSupplier) {
this.originalSupplier = originalSupplier;
}
@Override
public T get() {
if (cachedValue == null) {
cachedValue = originalSupplier.get();
}
return cachedValue;
}
}
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier) {
return new CachingSupplier<>(valueSupplier);
}
Maybe that's easier to understand. If you are still unclear about something, just ask in a comment and I'll try to explain it.