Class Memoizer<T>

java.lang.Object
org.apache.juneau.commons.function.Memoizer<T>
Type Parameters:
T - The type of value supplied.
All Implemented Interfaces:
Supplier<T>, NullableSupplier<T>
Direct Known Subclasses:
Setting

public class Memoizer<T> extends Object implements NullableSupplier<T>
A thread-safe supplier that caches the result of the first call and supports resetting the cache.

This class extends NullableSupplier to provide both standard Supplier.get() functionality and a reset() method to clear the cache, forcing recomputation on the next call to get(). It also inherits all Optional-like convenience methods from NullableSupplier.

Usage:

// Create a memoizer Memoizer<String> supplier = new Memoizer<>(() -> expensiveComputation()); // First call computes and caches String result1 = supplier.get(); // Subsequent calls return cached value String result2 = supplier.get(); // Use Optional-like methods if (supplier.isPresent()) { String upper = supplier.map(String::toUpperCase).orElse("default"); } // Reset forces recomputation on next get() supplier.reset(); String result3 = supplier.get(); // Recomputes

Thread Safety:

This class is thread-safe for both get() and reset() operations. If multiple threads call get() simultaneously after a reset, the supplier may be invoked multiple times, but only one result will be cached.

Notes:
  • The supplier may be called multiple times if threads race, but only one result is cached.
  • The cached value can be null if the supplier returns null.
  • After reset, the next get() will recompute the value.
  • This is particularly useful for testing when configuration changes and cached values need to be recalculated.
  • Inherits all Optional-like methods from NullableSupplier (isPresent(), isEmpty(), map(), orElse(), etc.).
See Also:
  • Constructor Details

    • Memoizer

      public Memoizer(Supplier<T> supplier)
      Constructor.
      Parameters:
      supplier - The underlying supplier to call when computing values. Must not be null.
  • Method Details

    • get

      public T get()
      Returns the cached value if present, otherwise computes it using the underlying supplier.
      Specified by:
      get in interface Supplier<T>
      Returns:
      The cached or newly computed value.
    • reset

      public void reset()
      Clears the cached value, forcing the next call to get() to recompute the value.

      This method is thread-safe and can be called from multiple threads. After reset, the next get() call will invoke the underlying supplier to compute a fresh value.

    • set

      public void set(T value)
      Sets the cached value directly without invoking the underlying supplier.

      This method allows you to override the cached value, bypassing the supplier. Subsequent calls to get() will return the set value until reset() is called or the value is set again.

      This method is thread-safe and is particularly useful for testing when you need to inject a specific value without invoking the supplier.

      Example:

      // Create a memoizer Memoizer<String> supplier = new Memoizer<>(() -> "computed"); // Set a value directly without invoking the supplier supplier.set("injected"); // get() returns the injected value assertEquals("injected", supplier.get()); // Reset clears the cache, next get() will invoke the supplier supplier.reset(); assertEquals("computed", supplier.get());

      Parameters:
      value - The value to cache. Can be null.
    • isSupplied

      public boolean isSupplied()
      Returns true if the supplier has not yet been called (cache is empty).

      This method checks whether the cached value is null, which indicates that get() has not yet been called, or the cache was reset.

      Returns:
      true if the supplier has not been called yet, false if a value has been cached.
    • copy

      public Memoizer<T> copy()
      Creates a copy of this memoizer.

      If a value has been cached, the copy will use a supplier that returns that cached value. If no value has been cached yet, the copy will use the original supplier.

      Returns:
      A new Memoizer instance with the same state as this memoizer.
    • map

      public <U> Memoizer<U> map(Function<? super T,? extends U> mapper)
      If a value is present, applies the provided mapping function to it and returns a Memoizer describing the result.

      The returned Memoizer maintains its own cache, independent of this memoizer. Resetting the mapped memoizer does not affect this memoizer, and vice versa.

      Specified by:
      map in interface NullableSupplier<T>
      Type Parameters:
      U - The type of the result of the mapping function.
      Parameters:
      mapper - A mapping function to apply to the value, if present. Must not be null.
      Returns:
      A Memoizer describing the result of applying a mapping function to the value of this Memoizer, if a value is present, otherwise an empty Memoizer.
    • filter

      public Memoizer<T> filter(Predicate<? super T> predicate)
      If a value is present, and the value matches the given predicate, returns a Memoizer describing the value, otherwise returns an empty Memoizer.

      The returned Memoizer maintains its own cache, independent of this memoizer. Resetting the filtered memoizer does not affect this memoizer, and vice versa.

      Specified by:
      filter in interface NullableSupplier<T>
      Parameters:
      predicate - A predicate to apply to the value, if present. Must not be null.
      Returns:
      A Memoizer describing the value of this Memoizer if a value is present and the value matches the given predicate, otherwise an empty Memoizer.