diff --git a/src/main/java/org/springframework/data/util/Lazy.java b/src/main/java/org/springframework/data/util/Lazy.java index 4634fa064..c0be59c8a 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 @@ import org.springframework.util.ObjectUtils; /** * 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 @@ public class Lazy implements Supplier { } /** - * 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 class Lazy implements Supplier { } /** - * 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 class Lazy implements Supplier { } /** - * 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,119 +119,10 @@ public class Lazy implements Supplier { 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 - */ - 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. - * - * @param supplier must not be {@literal null}. - * @return - */ - public Lazy or(Supplier supplier) { - - Assert.notNull(supplier, "Supplier must not be null"); - - return Lazy.of(() -> orElseGet(supplier)); - } - - /** - * Returns a new Lazy that will return the given value in case the current one does not yield in a result. - * - * @param value must not be {@literal null}. - * @return - */ - public Lazy or(T value) { - - Assert.notNull(value, "Value must not be null"); - - return Lazy.of(() -> orElse(value)); - } - - /** - * Returns the value of the lazy computation or the given default value in case the computation yields - * {@literal null}. - * - * @param value - * @return - */ - @Nullable - public T orElse(@Nullable T value) { - - T nullable = getNullable(); - - return nullable == null ? value : 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 - */ - @Nullable - public T orElseGet(Supplier supplier) { - - Assert.notNull(supplier, "Default value supplier must not be null"); - - T value = getNullable(); - - return value == null ? supplier.get() : value; - } - - /** - * Creates a new {@link Lazy} with the given {@link Function} lazily applied to the current one. - * - * @param function must not be {@literal null}. - * @return - */ - public Lazy map(Function function) { - - Assert.notNull(function, "Function must not be null"); - - return Lazy.of(() -> function.apply(get())); - } - - /** - * Creates a new {@link Lazy} with the given {@link Function} lazily applied to the current one. - * - * @param function must not be {@literal null}. - * @return - */ - public Lazy flatMap(Function> function) { - - Assert.notNull(function, "Function must not be null"); - - 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 + * @return the value of the lazy evaluation, can be {@literal null}. * @since 2.2 */ @Nullable @@ -249,14 +138,102 @@ public class Lazy implements Supplier { return value; } - @Override - public String toString() { + /** + * 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 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()); + } - if (!resolved) { - return UNRESOLVED; - } + /** + * Returns a new {@code Lazy} that will return the given value in case the current one does not yield in a result. + * + * @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(T other) { - return value == null ? "null" : value.toString(); + Assert.notNull(other, "Other value must not be null"); + + return Lazy.of(() -> orElse(other)); + } + + /** + * Returns a new {@code Lazy} that will consume the given supplier in case the current one does not yield in a result. + * + * @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(Supplier supplier) { + + Assert.notNull(supplier, "Supplier must not be null"); + + 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 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 other) { + + T nullable = getNullable(); + + 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 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) { + + Assert.notNull(supplier, "Default value supplier must not be null"); + + T value = getNullable(); + + return value == null ? supplier.get() : value; + } + + /** + * Creates a new {@code Lazy} with the given {@link Function} lazily applied to the current one. + * + * @param function must not be {@literal null}. + * @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) { + + Assert.notNull(function, "Function must not be null"); + + return Lazy.of(() -> function.apply(get())); + } + + /** + * Creates a new {@code Lazy} with the given {@link Function} lazily applied to the current one. + * + * @param function must not be {@literal null}. + * @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) { + + Assert.notNull(function, "Function must not be null"); + + return Lazy.of(() -> function.apply(get()).get()); } @Override @@ -291,4 +268,29 @@ public class Lazy implements Supplier { 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 37c10c528..b40344d50 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 @@ class LazyUnitTests { @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 @@ class LazyUnitTests { 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); }