diff --git a/src/main/java/org/springframework/data/util/Lazy.java b/src/main/java/org/springframework/data/util/Lazy.java index 4634fa0640..c0be59c8a5 100644 --- a/src/main/java/org/springframework/data/util/Lazy.java +++ b/src/main/java/org/springframework/data/util/Lazy.java @@ -25,8 +25,10 @@ /** * Simple value type to delay the creation of an object using a {@link Supplier} returning the produced object for - * subsequent lookups. Note, that no concurrency control is applied during the lookup of {@link #get()}, which means in - * concurrent access scenarios, the provided {@link Supplier} can be called multiple times. + * subsequent lookups. + *

+ * Note, that no concurrency control is applied during the lookup of {@link #get()}, which means in concurrent access + * scenarios, the provided {@link Supplier} can be called multiple times. * * @author Oliver Gierke * @author Mark Paluch @@ -45,17 +47,12 @@ public class Lazy implements Supplier { private @Nullable T value; private volatile boolean resolved; - /** - * Creates a new {@link Lazy} instance for the given supplier. - * - * @param supplier - */ private Lazy(Supplier supplier) { this(supplier, null, false); } /** - * Creates a new {@link Lazy} for the given {@link Supplier}, value and whether it has been resolved or not. + * Creates a new {@code Lazy} for the given {@link Supplier}, value and whether it has been resolved or not. * * @param supplier must not be {@literal null}. * @param value can be {@literal null}. @@ -69,22 +66,22 @@ private Lazy(Supplier supplier, @Nullable T value, boolean resolved } /** - * Creates a new {@link Lazy} to produce an object lazily. + * Creates a new {@code Lazy} to produce an object lazily. * * @param the type of which to produce an object of eventually. * @param supplier the {@link Supplier} to create the object lazily. - * @return + * @return a {@code Lazy} wrapping the given {@link Supplier}. */ public static Lazy of(Supplier supplier) { return new Lazy<>(supplier); } /** - * Creates a new {@link Lazy} to return the given value. + * Creates a new {@code Lazy} to return the given value. * * @param the type of the value to return eventually. * @param value the value to return. - * @return + * @return a {@code Lazy} wrapping {@code value}. */ public static Lazy of(T value) { @@ -94,9 +91,9 @@ public static Lazy of(T value) { } /** - * Creates a pre-resolved empty {@link Lazy}. + * Creates a pre-resolved empty {@code Lazy}. * - * @return + * @return an empty {@code Lazy}. * @since 2.1 */ @SuppressWarnings("unchecked") @@ -105,11 +102,12 @@ public static Lazy empty() { } /** - * Returns the value created by the configured {@link Supplier}. Will return the calculated instance for subsequent - * lookups. + * Returns the value created by the configured {@link Supplier}. Will return the same instance for subsequent lookups. * - * @return + * @return the value created by the configured {@link Supplier}. Will return the same instance for subsequent lookups. + * @throws IllegalStateException if the resolved value is {@literal null}. */ + @Override public T get() { T value = getNullable(); @@ -121,63 +119,84 @@ public T get() { return value; } + /** + * Returns the value of the lazy evaluation. + * + * @return the value of the lazy evaluation, can be {@literal null}. + * @since 2.2 + */ + @Nullable + public T getNullable() { + + if (resolved) { + return value; + } + + this.value = supplier.get(); + this.resolved = true; + + return value; + } + /** * Returns the {@link Optional} value created by the configured {@link Supplier}, allowing the absence of values in * contrast to {@link #get()}. Will return the calculated instance for subsequent lookups. * - * @return + * @return an {@link Optional} value created by the configured {@link Supplier} or an empty {@link Optional} if the + * resolved value is {@literal null}. */ public Optional getOptional() { return Optional.ofNullable(getNullable()); } /** - * Returns a new Lazy that will consume the given supplier in case the current one does not yield in a result. + * Returns a new {@code Lazy} that will return the given value in case the current one does not yield in a result. * - * @param supplier must not be {@literal null}. - * @return + * @param other must not be {@literal null}. + * @return a new {@code Lazy} that will yield its value if present, otherwise {@code other}. */ - public Lazy or(Supplier supplier) { + public Lazy or(T other) { - Assert.notNull(supplier, "Supplier must not be null"); + Assert.notNull(other, "Other value must not be null"); - return Lazy.of(() -> orElseGet(supplier)); + return Lazy.of(() -> orElse(other)); } /** - * Returns a new Lazy that will return the given value in case the current one does not yield in a result. + * Returns a new {@code Lazy} that will consume the given supplier in case the current one does not yield in a result. * - * @param value must not be {@literal null}. - * @return + * @param supplier the supplying function that produces a value to be returned, must not be {@literal null}. + * @return a new {@code Lazy} that will yield its value if present, otherwise the result produced by the supplying + * function. */ - public Lazy or(T value) { + public Lazy or(Supplier supplier) { - Assert.notNull(value, "Value must not be null"); + Assert.notNull(supplier, "Supplier must not be null"); - return Lazy.of(() -> orElse(value)); + return Lazy.of(() -> orElseGet(supplier)); } /** * Returns the value of the lazy computation or the given default value in case the computation yields * {@literal null}. * - * @param value - * @return + * @param other the value to be returned, if no value is present. May be {@literal null}. + * @return the value, if present, otherwise {@code other}. */ @Nullable - public T orElse(@Nullable T value) { + public T orElse(@Nullable T other) { T nullable = getNullable(); - return nullable == null ? value : nullable; + return nullable == null ? other : nullable; } /** * Returns the value of the lazy computation or the value produced by the given {@link Supplier} in case the original * value is {@literal null}. * - * @param supplier must not be {@literal null}. - * @return + * @param supplier the supplying function that produces a value to be returned, must not be {@literal null}. + * @return the value, if present, otherwise the result produced by the supplying function. */ @Nullable public T orElseGet(Supplier supplier) { @@ -190,10 +209,11 @@ public T orElseGet(Supplier supplier) { } /** - * Creates a new {@link Lazy} with the given {@link Function} lazily applied to the current one. + * Creates a new {@code Lazy} with the given {@link Function} lazily applied to the current one. * * @param function must not be {@literal null}. - * @return + * @return an {@code Lazy} describing the result of applying a mapping function to the value of this {@code Lazy} or + * throwing {@link IllegalStateException} if the {@code Lazy} is empty. */ public Lazy map(Function function) { @@ -203,10 +223,11 @@ public Lazy map(Function function) { } /** - * Creates a new {@link Lazy} with the given {@link Function} lazily applied to the current one. + * Creates a new {@code Lazy} with the given {@link Function} lazily applied to the current one. * * @param function must not be {@literal null}. - * @return + * @return the result of applying an {@code Lazy}-bearing mapping function to the value of this {@code Lazy} or a + * {@code Lazy} throwing {@link IllegalStateException} if the {@code Lazy} is empty. */ public Lazy flatMap(Function> function) { @@ -215,50 +236,6 @@ public Lazy flatMap(Function> function) { return Lazy.of(() -> function.apply(get()).get()); } - /** - * Returns the {@link String} representation of the already resolved value or the one provided through the given - * {@link Supplier} if the value has not been resolved yet. - * - * @param fallback must not be {@literal null}. - * @return will never be {@literal null}. - * @since 3.0.1 - */ - public String toString(Supplier fallback) { - - Assert.notNull(fallback, "Fallback must not be null!"); - - return resolved ? toString() : fallback.get(); - } - - /** - * Returns the value of the lazy evaluation. - * - * @return - * @since 2.2 - */ - @Nullable - public T getNullable() { - - if (resolved) { - return value; - } - - this.value = supplier.get(); - this.resolved = true; - - return value; - } - - @Override - public String toString() { - - if (!resolved) { - return UNRESOLVED; - } - - return value == null ? "null" : value.toString(); - } - @Override public boolean equals(@Nullable Object o) { @@ -291,4 +268,29 @@ public int hashCode() { return result; } + + @Override + public String toString() { + + if (!resolved) { + return UNRESOLVED; + } + + return value == null ? "null" : value.toString(); + } + + /** + * Returns the {@link String} representation of the already resolved value or the one provided through the given + * {@link Supplier} if the value has not been resolved yet. + * + * @param fallback must not be {@literal null}. + * @return will never be {@literal null}. + * @since 3.0.1 + */ + public String toString(Supplier fallback) { + + Assert.notNull(fallback, "Fallback must not be null!"); + + return resolved ? toString() : fallback.get(); + } } diff --git a/src/test/java/org/springframework/data/util/LazyUnitTests.java b/src/test/java/org/springframework/data/util/LazyUnitTests.java index 37c10c5283..b40344d503 100755 --- a/src/test/java/org/springframework/data/util/LazyUnitTests.java +++ b/src/test/java/org/springframework/data/util/LazyUnitTests.java @@ -70,7 +70,7 @@ void returnsLastValueInChain() { @Test void returnsCachedInstanceOnMultipleAccesses() { - var lazy = Lazy.of(() -> new Object()); + var lazy = Lazy.of(Object::new); assertThat(lazy.get()).isSameAs(lazy.get()); } @@ -113,6 +113,7 @@ void returnsElseValue() { var empty = Lazy.of(() -> null); assertThat(empty.orElse(reference)).isEqualTo(reference); + assertThat(empty.orElseGet(() -> reference)).isEqualTo(reference); assertThat(empty.or(reference).get()).isEqualTo(reference); assertThat(empty.or(() -> reference).get()).isEqualTo(reference); }