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();
Suppliers. memoize is a simple method that takes a Supplier and returns a new Supplier that caches the value returned from the supplied Supplier. get() method. This convenient helper allows us to turn any Supplier into a lazily loaded cached value.
Memoization is a specific form of caching that involves caching the return value of a function based on its parameters. Caching is a more general term; for example, HTTP caching is caching but not memoization.
In Java 8, Supplier is a simple functional interface, which is represents an operator that provides a value for each call. Supplier has only one get() method and has no default method. Java Functional Interface.
The Java Object Cache provides caching for expensive or frequently used Java objects when the application servers use a Java program to supply their content. Cached Java objects can contain generated pages or can provide support objects within the program to assist in creating new content.
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.
How about this?
public static <T> Supplier<T> memoize(final Supplier<? extends T> factory) {
final List<T> cache = new ArrayList<>();
return () -> {
// v--- check the value is cached?
if (cache.isEmpty()) {
// v--- return the value created by factory
cache.add(factory.get());
// ^--- adding the value into the cache
}
return cache.get(0);
// ^--- return the cached value
};
}
Supplier<String> factory = ()-> new String("foo");
assert factory.get() == factory.get(); // return false;
assert memoize(factory).get() == memoize(factory).get(); //return false;
// v--- storing the memoized factory for using as further
Supplier<String> memoized = memoize(original);
assert memoized.get() == memoized.get(); // return true.
// ^--- they are the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With