Caching using Supplier Java 8

memor1s :

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();
Rolf Schäuble :

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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=461325&siteId=1