Class Lazy<T>
- Type Parameters:
T- the type of the lazily evaluated value
The supplier passed to of(Supplier) is not invoked until the first call to
get(). Subsequent calls return the cached result without invoking the supplier again.
Memoization is thread-safe via a volatile Try<T> state field and
double-checked locking: the first read is lock-free; if the state is null, a
synchronized block is entered and the state is checked again before evaluating
the supplier. Both successful values and supplier exceptions are stored in the state as a
Try, so any exception thrown during evaluation is memoized and rethrown on every
subsequent get() call without re-invoking the supplier. The thread-safety design
is documented in
ADR-012 — Lazy<T> with volatile Try<T> and double-checked locking.
This type is @NullMarked: the supplier must return a non-null value.
Use Lazy<Option<T>> to model a lazily evaluated optional result.
-
Method Summary
Modifier and TypeMethodDescription<R> Lazy<R> Returns a newLazyby applyingfto this value and flattening the result.static <T> Lazy<T> fromFuture(CompletableFuture<? extends T> future) get()Returns the value, evaluating the supplier on the first call and caching the result.booleanReturnstrueif the supplier has already been evaluated.<R> Lazy<R> Returns a newLazythat appliesfto this value when evaluated.static <T> Lazy<T> toEither()Evaluates thisLazyinside anEither, capturing any exception thrown by the supplier asLeft(Throwable).Evaluates thisLazyinside anEither, converting any exception thrown by the supplier into a typed left value usingerrorMapper.toFuture()Converts thisLazyinto aCompletableFuture.toOption()Evaluates thisLazyand wraps the result in anOption.Evaluates thisLazyand returns the value wrapped in aOptional.toResult()Evaluates thisLazyinside aResult, capturing any exception thrown by the supplier asErr(Throwable).Evaluates thisLazyinside aResult, converting any exception thrown by the supplier into a typed error usingerrorMapper.toString()Returns a string representation of thisLazy.toTry()
-
Method Details
-
of
- Type Parameters:
T- the type of the value- Parameters:
supplier- the supplier to evaluate lazily; must not benull- Returns:
- a new, unevaluated
Lazy<T> - Throws:
NullPointerException- ifsupplierisnull
-
get
Returns the value, evaluating the supplier on the first call and caching the result.The supplier is called at most once. All subsequent calls return the cached value. This method is thread-safe.
- Returns:
- the (possibly cached) value; never
null - Throws:
NullPointerException- if the supplier returnsnull
-
isEvaluated
public boolean isEvaluated()Returnstrueif the supplier has already been evaluated.- Returns:
trueafter the first call toget(),falsebefore
-
map
Returns a newLazythat appliesfto this value when evaluated.The mapping function is not invoked until
get()is called on the returnedLazy. Evaluating the returnedLazyalso evaluates this one.- Type Parameters:
R- the type of the mapped value- Parameters:
f- the mapping function; must not benulland must not returnnull- Returns:
- a new, unevaluated
Lazy<R> - Throws:
NullPointerException- iffisnull
-
flatMap
Returns a newLazyby applyingfto this value and flattening the result.Neither this value nor the function is evaluated until
get()is called on the returnedLazy.- Type Parameters:
R- the type of the resulting value- Parameters:
f- a function that returns aLazy<R>; must not benull- Returns:
- a new, unevaluated
Lazy<R> - Throws:
NullPointerException- iffisnullor returnsnull
-
toOption
Evaluates thisLazyand wraps the result in anOption.Unlike
toTry(), this method does not capture exceptions — any unchecked throwable (RuntimeExceptionorError) thrown by the supplier propagates to the caller, with the same semantics asget(). UsetoTry().toOption()if you need exception-safe conversion.- Returns:
Option.some(value)- Throws:
RuntimeException- if the supplier throws aRuntimeExceptionError- if the supplier throws anError
-
toTry
Evaluates thisLazyinside aTry, capturing any exception thrown by the supplier as aFailure.The result is memoized: the supplier is called at most once regardless of how many times this method is invoked.
- Returns:
Success(value)if the supplier completes normally, orFailure(exception)if it throws
-
fromFuture
Creates aLazythat defers the blocking wait forfutureuntil the first call toget().The future's result is obtained via
Try.fromFuture(CompletableFuture), which unwrapsCompletionExceptiontransparently. If the future completed exceptionally,get()rethrows the originalRuntimeExceptionorErroras-is, and wraps checked exceptions in a newRuntimeException.- Type Parameters:
T- the type of the future's value- Parameters:
future- theCompletableFutureto wrap; must not benull- Returns:
- a new, unevaluated
Lazy<T> - Throws:
NullPointerException- iffutureisnull
-
toFuture
Converts thisLazyinto aCompletableFuture.If the value has already been evaluated (i.e.,
isEvaluated()istrue), returns an already-completed future with the cached value — no thread pool dispatch occurs. Otherwise, evaluates the supplier asynchronously viaCompletableFuture.supplyAsync(Supplier).- Returns:
- a
CompletableFuture<T>that completes with this lazy's value
-
toResult
-
toResult
Evaluates thisLazyinside aResult, converting any exception thrown by the supplier into a typed error usingerrorMapper.- Type Parameters:
E- the error type- Parameters:
errorMapper- a function that converts the thrown exception to the error value; must not benulland must not returnnull- Returns:
Ok(value)if the supplier completes normally, orErr(errorMapper.apply(exception))if it throws- Throws:
NullPointerException- iferrorMapperisnullor returnsnull
-
toOptional
Evaluates thisLazyand returns the value wrapped in aOptional.Unlike
toTry(), this method does not capture exceptions — any unchecked throwable (RuntimeExceptionorError) thrown by the supplier propagates to the caller, with the same semantics asget(). UsetoTry().toOptional()if you need exception-safe conversion.- Returns:
Optional.of(value); neverOptional.empty()- Throws:
RuntimeException- if the supplier throws aRuntimeExceptionError- if the supplier throws anError
-
toEither
-
toEither
Evaluates thisLazyinside anEither, converting any exception thrown by the supplier into a typed left value usingerrorMapper.- Type Parameters:
E- the left (error) type- Parameters:
errorMapper- a function that converts the thrown exception to the left value; must not benulland must not returnnull- Returns:
Either.right(value)if the supplier completes normally, orEither.left(errorMapper.apply(exception))if it throws- Throws:
NullPointerException- iferrorMapperisnullor returnsnull
-
toString
-