Interface StableValue<T>
- Type Parameters:
T
- type of the holder value
StableValue
is a preview API of the Java platform.
A stable value is said to be monotonic because the state of a stable value can only go from unset to set and consequently, a value can only be set at most once.
StableValue is mainly intended to be a member of a holding class and is usually neither exposed directly via accessors nor passed as a method parameter.
Factories
To create a new fresh (unset) StableValue, use the StableValue::newInstance factory.
This class also contains a number of convenience methods for creating constructs involving stable values:
-
A caching (also called "memoized") Supplier, where a given
original
Supplier is guaranteed to be successfully invoked at most once even in a multithreaded environment, can be created like this:Supplier<T> cache = StableValue.newCachingSupplier(original);
-
A caching (also called "memoized") IntFunction, for the allowed given
size
input values[0, size)
and where the givenoriginal
IntFunction is guaranteed to be successfully invoked at most once per inout index even in a multithreaded environment, can be created like this:IntFunction<R> cache = StableValue.newCachingIntFunction(size, original);
-
A caching (also called "memoized") Function, for the given set of allowed
inputs
and where the givenoriginal
function is guaranteed to be successfully invoked at most once per input value even in a multithreaded environment, can be created like this:Function<T, R> cache = StableValue.newCachingFunction(inputs, original);
-
A lazy List of stable elements with a given
size
and givenmapper
can be created the following way:List<E> lazyList = StableValue.lazyList(size, mapper);
-
A lazy Map with a given set of
keys
and givenmapper
associated with stable values can be created like this:Map<K, V> lazyMap = StableValue.lazyMap(keys, mapper);
The constructs above are eligible for similar JVM optimizations as StableValue instances.
Memory Consistency Properties
Actions on a presumptive holder value in a thread prior to calling a method that sets the holder value are seen by any other thread that observes a set holder value. More generally, the action of attempting to interact (i.e. via load or store operations) with a StableValue's holder value (e.g. viatrySet(T)
or
orElseThrow()
) forms a
happens-before
relation between any other attempt to interact with the StableValue's holder value.
Nullability
Except for a StableValue's holder value itself, all method parameters must be non-null or aNullPointerException
will be thrown.- Implementation Note:
- Implementing classes are free to synchronize on
this
and consequently, care should be taken whenever (directly or indirectly) synchronizing on a StableValue. Failure to do this may lead to deadlock., Instance fields explicitly declared as StableValue or one-dimensional arrays thereof are eligible for certain JVM optimizations compared to normal instance fields. This comes with restrictions on reflective modifications. Although most ways of reflective modification of such fields are disabled, it is strongly discouraged to circumvent these protection means as reflectively modifying such fields may lead to unspecified behavior. - Since:
- 24
-
Method Summary
Modifier and TypeMethodDescriptioncomputeIfUnset
(Supplier<? extends T> supplier) Returns the set holder value if set, otherwise attempts to compute and set a new (nullable) value using the providedsupplier
, returning the (pre-existing or newly set) value.boolean
isSet()
Returnstrue
if a holder value is set,false
otherwise.static <T> List
<T> lazyList
(int size, IntFunction<? extends T> mapper) Returns a lazy, shallowly immutable, stable List of the providedsize
where the individual elements of the list are lazily computed via the providedmapper
whenever an element is first accessed (directly or indirectly), for example via List::get.static <K,
V> Map <K, V> Returns a lazy, shallowly immutable, stable Map of the providedkeys
where the associated values of the maps are lazily computed vio the providedmapper
whenever a value is first accessed (directly or indirectly), for example via Map::get.static <T,
R> Function <T, R> newCachingFunction
(Set<? extends T> inputs, Function<? super T, ? extends R> original) Returns a new caching, thread-safe, stable, lazily computedFunction
that, for each allowed input in the given set ofinputs
, records the values of the providedoriginal
Function upon being first accessed via Function::apply, or optionally via background threads created from the providedfactory
(if non-null).static <R> IntFunction
<R> newCachingIntFunction
(int size, IntFunction<? extends R> original) Returns a new caching, thread-safe, stable, lazily computedIntFunction
that, for each allowed input, records the values of the providedoriginal
IntFunction upon being first accessed via IntFunction::apply.static <T> Supplier
<T> newCachingSupplier
(Supplier<? extends T> original) Returns a new caching, thread-safe, stable, lazily computed supplier that records the value of the providedoriginal
supplier upon being first accessed via Supplier::get.static <T> StableValuePREVIEW
<T> Returns a fresh stable value with an unset holder value.Returns the set holder value (nullable) if set, otherwise return theother
value.Returns the set holder value if set, otherwise throwsNoSuchElementException
.default void
setOrThrow
(T value) Sets the holder value to the providedvalue
, or, if already set, throwsIllegalStateException
}boolean
Returnstrue
if the holder value was set to the providedvalue
, otherwise returnsfalse
.
-
Method Details
-
trySet
Returnstrue
if the holder value was set to the providedvalue
, otherwise returnsfalse
.When this method returns, a holder value is always set.
- Parameters:
value
- to set (nullable)- Returns:
true
if the holder value was set to the providedvalue
, otherwise returnsfalse
-
orElse
-
orElseThrow
T orElseThrow()Returns the set holder value if set, otherwise throwsNoSuchElementException
.- Returns:
- the set holder value if set, otherwise throws
NoSuchElementException
- Throws:
NoSuchElementException
- if no value is set
-
isSet
boolean isSet()Returnstrue
if a holder value is set,false
otherwise.- Returns:
true
if a holder value is set,false
otherwise
-
setOrThrow
Sets the holder value to the providedvalue
, or, if already set, throwsIllegalStateException
}When this method returns (or throws an Exception), a holder value is always set.
- Parameters:
value
- to set (nullable)- Throws:
IllegalStateException
- if a holder value is already set
-
computeIfUnset
Returns the set holder value if set, otherwise attempts to compute and set a new (nullable) value using the providedsupplier
, returning the (pre-existing or newly set) value.The provided
supplier
is guaranteed to be invoked at most once if it completes without throwing an exception.If the supplier throws an (unchecked) exception, the exception is rethrown, and no value is set. The most common usage is to construct a new object serving as a lazily computed value or memoized result, as in:
Value witness = stable.computeIfUnset(Value::new);
- Implementation Requirements:
- The implementation logic is equivalent to the following steps for this
stable
:if (stable.isSet()) { return stable.get(); } else { V newValue = supplier.get(); stable.setOrThrow(newValue); return newValue; }
supplier
will only be invoked once even if invoked from several threads unless thesupplier
throws an exception. - Parameters:
supplier
- to be used for computing a value- Returns:
- the set holder value if set, otherwise attempts to compute and set a
new (nullable) value using the provided
supplier
, returning the (pre-existing or newly set) value - Throws:
StackOverflowError
- if the providedsupplier
recursively invokes the providedsupplier
upon being invoked.
-
newInstance
Returns a fresh stable value with an unset holder value.- Type Parameters:
T
- type of the holder value- Returns:
- a fresh stable value with an unset holder value
-
newCachingSupplier
Returns a new caching, thread-safe, stable, lazily computed supplier that records the value of the providedoriginal
supplier upon being first accessed via Supplier::get.The provided
original
supplier is guaranteed to be successfully invoked at most once even in a multi-threaded environment. Competing threads invoking the Supplier::get method when a value is already under computation will block until a value is computed or an exception is thrown by the computing thread.If the
original
Supplier invokes the returned Supplier recursively, a StackOverflowError will be thrown when the returned Supplier's Supplier::get method is invoked.If the provided
original
supplier throws an exception, it is relayed to the initial caller.- Type Parameters:
T
- the type of results supplied by the returned supplier- Parameters:
original
- supplier used to compute a memoized value- Returns:
- a new caching, thread-safe, stable, lazily computed
supplier that records the value of the provided
original
supplier upon being first accessed via Supplier::get
-
newCachingIntFunction
Returns a new caching, thread-safe, stable, lazily computedIntFunction
that, for each allowed input, records the values of the providedoriginal
IntFunction upon being first accessed via IntFunction::apply.The provided
original
IntFunction is guaranteed to be successfully invoked at most once per allowed input, even in a multi-threaded environment. Competing threads invoking the IntFunction::apply method when a value is already under computation will block until a value is computed or an exception is thrown by the computing thread.If the
original
IntFunction invokes the returned IntFunction recursively for a particular input value, a StackOverflowError will be thrown when the returned IntFunction's IntFunction::apply method is invoked.If the provided
original
IntFunction throws an exception, it is relayed to the initial caller.- Type Parameters:
R
- the type of results delivered by the returned IntFunction- Parameters:
size
- the size of the allowed inputs in[0, size)
original
- IntFunction used to compute a memoized value- Returns:
- a new caching, thread-safe, stable, lazily computed
IntFunction
that, for each allowed input, records the values of the providedoriginal
IntFunction upon being first accessed via IntFunction::apply
-
newCachingFunction
static <T,R> Function<T,R> newCachingFunction(Set<? extends T> inputs, Function<? super T, ? extends R> original) Returns a new caching, thread-safe, stable, lazily computedFunction
that, for each allowed input in the given set ofinputs
, records the values of the providedoriginal
Function upon being first accessed via Function::apply, or optionally via background threads created from the providedfactory
(if non-null).The provided
original
Function is guaranteed to be successfully invoked at most once per allowed input, even in a multi-threaded environment. Competing threads invoking the Function::apply method when a value is already under computation will block until a value is computed or an exception is thrown by the computing thread.If the
original
Function invokes the returned Function recursively for a particular input value, a StackOverflowError will be thrown when the returned Function's Function::apply method is invoked.If the provided
original
Function throws an exception, it is relayed to the initial caller. If the memoized Function is computed by a background thread, exceptions from the providedoriginal
Function will be relayed to the background thread's uncaught exception handler.The order in which background threads are started is unspecified.
- Type Parameters:
T
- the type of the input to the returned FunctionR
- the type of results delivered by the returned Function- Parameters:
inputs
- the set of allowed input valuesoriginal
- Function used to compute a memoized value- Returns:
- a new caching, thread-safe, stable, lazily computed
Function
that, for each allowed input in the given set ofinputs
, records the values of the providedoriginal
Function upon being first accessed via Function::apply, or optionally via background threads created from the providedfactory
(if non-null)
-
lazyList
Returns a lazy, shallowly immutable, stable List of the providedsize
where the individual elements of the list are lazily computed via the providedmapper
whenever an element is first accessed (directly or indirectly), for example via List::get.The provided
mapper
IntFunction is guaranteed to be successfully invoked at most once per list index, even in a multi-threaded environment. Competing threads accessing an element already under computation will block until an element is computed or an exception is thrown by the computing thread.If the
mapper
IntFunction invokes the returned IntFunction recursively for a particular index, a StackOverflowError will be thrown when the returned List's List::get method is invoked.If the provided
mapper
IntFunction throws an exception, it is relayed to the initial caller and no element is computed.The returned List is not
Serializable
- Type Parameters:
T
- theStableValue
s' element type- Parameters:
size
- the size of the returned listmapper
- to invoke whenever an element is first accessed (may return null)- Returns:
- a lazy, shallowly immutable, stable List of the provided
size
where the individual elements of the list are lazily computed via the providedmapper
whenever an element is first accessed (directly or indirectly), for example via List::get
-
lazyMap
Returns a lazy, shallowly immutable, stable Map of the providedkeys
where the associated values of the maps are lazily computed vio the providedmapper
whenever a value is first accessed (directly or indirectly), for example via Map::get.The provided
mapper
Function is guaranteed to be successfully invoked at most once per key, even in a multi-threaded environment. Competing threads accessing an associated value already under computation will block until an associated value is computed or an exception is thrown by the computing thread.If the
mapper
Function invokes the returned Map recursively for a particular key, a StackOverflowError will be thrown when the returned Map's Map::get} method is invoked.If the provided
mapper
Function throws an exception, it is relayed to the initial caller and no value is computed.The returned Map is not
Serializable
- Type Parameters:
K
- the type of keys maintained by the returned mapV
- the type of mapped values- Parameters:
keys
- the keys in the returned mapmapper
- to invoke whenever an associated value is first accessed (may return null)- Returns:
- a lazy, shallowly immutable, stable Map of the provided
keys
where the associated values of the maps are lazily computed vio the providedmapper
whenever a value is first accessed (directly or indirectly), for example via Map::get
-
StableValue
when preview features are enabled.