diff --git a/src/java.base/share/classes/java/lang/LazyConstant.java b/src/java.base/share/classes/java/lang/LazyConstant.java
index 85f9d0e82fd8f..e571e58654b74 100644
--- a/src/java.base/share/classes/java/lang/LazyConstant.java
+++ b/src/java.base/share/classes/java/lang/LazyConstant.java
@@ -29,7 +29,15 @@
 import jdk.internal.lang.LazyConstantImpl;
 
 import java.io.Serializable;
-import java.util.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
 import java.util.function.Function;
 import java.util.function.IntFunction;
 import java.util.function.Supplier;
@@ -49,8 +57,7 @@
  * the constant.
  * <p>
  * Once a lazy constant is initialized, its contents can <em>never change</em>
- * and will be retrieved over and over again upon subsequent {@linkplain #get() get()}
- * invocations.
+ * and will always be returned by subsequent {@linkplain #get() get()} invocations.
  * <p>
  * Consider the following example where a lazy constant field "{@code logger}" holds
  * an object of type {@code Logger}:
@@ -83,12 +90,20 @@
  * may result in storage resources being prepared.
  *
  * <h2 id="exception-handling">Exception handling</h2>
+ * If evaluation of the computing function throws an unchecked exception, the lazy
+ * constant is not initialized but instead transitions to an error state. Subsequent
+ * {@linkplain #get() get()} calls throw {@linkplain NoSuchElementException} without ever
+ * invoking the computing function again.
+ * <p>
+ * All failures are handled in this way. Here are two special cases that cause unchecked
+ * exceptions to be thrown:
+ * <p>
  * If the computing function returns {@code null}, a {@linkplain NullPointerException}
- * is thrown. Hence, a lazy constant can never hold a {@code null} value. Clients who
+ * is wrapped. Hence, a lazy constant can never hold a {@code null} value. Clients who
  * want to use a nullable constant can wrap the value into an {@linkplain Optional} holder.
  * <p>
  * If the computing function recursively invokes itself via the lazy constant, an
- * {@linkplain IllegalStateException} is thrown, and the lazy constant is not initialized.
+ * {@linkplain IllegalStateException} is wrapped.
  *
  * <h2 id="composition">Composing lazy constants</h2>
  * A lazy constant can depend on other lazy constants, forming a dependency graph
@@ -141,6 +156,8 @@
  * the constant {@linkplain java.util.concurrent##MemoryVisibility <em>happens-before</em>}
  * the initialized constant's content is read. Hence, the initialized constant's content,
  * including any {@code final} fields of any newly created objects, is safely published.
+ * As reading of the contents might be elided, there are no other memory ordering or
+ * visibility guarantees provided as a consequence of calling {@linkplain #get()}.
  * <p>
  * Thread interruption does not cancel the initialization of a lazy constant. In other
  * words, if the computing thread is interrupted, {@code LazyConstant::get} doesn't clear
@@ -161,14 +178,13 @@
  * to a lazy constant.
  *
  * <h2 id="miscellaneous">Miscellaneous</h2>
- * Except for {@linkplain Object#equals(Object) equals(obj)} and
- * {@linkplain #orElse(Object) orElse(other)} parameters, all method parameters
- * must be <em>non-null</em>, or a {@link NullPointerException} will be thrown.
+ * Except for {@linkplain Object#equals(Object) equals(obj)}, all method parameters must
+ * be <em>non-null</em>, or a {@link NullPointerException} will be thrown.
  *
  * @apiNote Once a lazy constant is initialized, its contents cannot ever be removed.
  *          This can be a source of an unintended memory leak. More specifically,
  *          a lazy constant {@linkplain java.lang.ref##reachability strongly references}
- *          it contents. Hence, the contents of a lazy constant will be reachable as long
+ *          its contents. Hence, the contents of a lazy constant will be reachable as long
  *          as the lazy constant itself is reachable.
  *          <p>
  *          While it's possible to store an array inside a lazy constant, doing so will
@@ -205,38 +221,26 @@ public sealed interface LazyConstant<T>
         permits LazyConstantImpl {
 
     /**
-     * {@return the contents of this lazy constant if initialized, otherwise,
-     *          returns {@code other}}
+     * {@return the initialized contents of this constant, computing it if necessary.}
      * <p>
-     * This method never triggers initialization of this lazy constant and will observe
-     * initialization by other threads atomically (i.e., it returns the contents
-     * if and only if the initialization has already completed).
-     *
-     * @param other value to return if the content is not initialized
-     *              (can be {@code null})
-     */
-    T orElse(T other);
-
-    /**
-     * {@return the contents of this initialized constant. If not initialized, first
-     *          computes and initializes this constant using the computing function}
+     *  If this constant is not initialized, first computes and initializes it
+     *  using the computing function.
      * <p>
      * After this method returns successfully, the constant is guaranteed to be
      * initialized.
      * <p>
-     * If the computing function throws, the throwable is relayed to the caller and
-     * the lazy constant remains uninitialized; a subsequent call to get() may then
-     * attempt the computation again.
-     */
-    T get();
-
-    /**
-     * {@return {@code true} if the constant is initialized, {@code false} otherwise}
+     * If the computing function throws an unchecked exception (i.e., a runtime exception
+     * or an error), this lazy constant is not initialized but transitions to an error
+     * state and a {@linkplain NoSuchElementException} with the unchecked exception as
+     * a cause is thrown.
      * <p>
-     * This method never triggers initialization of this lazy constant and will observe
-     * changes in the initialization state made by other threads atomically.
+     * Subsequent invocations of {@code get()} in the error state will also
+     * throw {@code NoSuchElementException} but with no cause and with a message
+     * that includes the name of the unchecked exception's class.
+     *
+     * @throws NoSuchElementException if initialization fails or has previously failed
      */
-    boolean isInitialized();
+    T get();
 
     // Object methods
 
@@ -280,19 +284,30 @@ public sealed interface LazyConstant<T>
     // Factory
 
     /**
-     * {@return a lazy constant whose contents is to be computed later via the provided
-     *          {@code computingFunction}}
+     * {@return a new lazy constant whose contents is to be computed later via the
+     *          provided {@code computingFunction}}
      * <p>
      * The returned lazy constant strongly references the provided
-     * {@code computingFunction} at least until initialization completes successfully.
+     * {@code computingFunction} until computation completes (successfully or with
+     * failure).
      * <p>
-     * If the provided computing function is already an instance of
-     * {@code LazyConstant}, the method is free to return the provided computing function
-     * directly.
+     * By design, the method always returns a new lazy constant even if the provided
+     * computing function is already an instance of {@code LazyConstant}. Clients that
+     * want to elide creation under this condition can write a utility method similar
+     * to the one in the snippet below and create lazy constants via this method rather
+     * than calling the built-in factory {@linkplain #of(Supplier)} directly:
+     *
+     * {@snippet lang = java:
+     * static <T> LazyConstant<T> ofFlattened(Supplier<? extends T> computingFunction) {
+     *     return (computingFunction instanceof LazyConstant<? extends T> lc)
+     *             ? (LazyConstant<T>) lc // unchecked cast is safe under normal generic usage
+     *             : LazyConstant.of(computingFunction);
+     *     }
+     * }
      *
-     * @implNote  after initialization completes successfully, the computing function is
-     *            no longer strongly referenced and becomes eligible for
-     *            garbage collection.
+     * @implNote  after the computing function completes (regardless of whether it
+     *            succeeds or throws an unchecked exception), the computing function is no
+     *            longer strongly referenced and becomes eligible for garbage collection.
      *
      * @param computingFunction in the form of a {@linkplain Supplier} to be used
      *                          to initialize the constant
@@ -302,9 +317,6 @@ public sealed interface LazyConstant<T>
     @SuppressWarnings("unchecked")
     static <T> LazyConstant<T> of(Supplier<? extends T> computingFunction) {
         Objects.requireNonNull(computingFunction);
-        if (computingFunction instanceof LazyConstant<? extends T> lc) {
-            return (LazyConstant<T>) lc;
-        }
         return LazyConstantImpl.ofLazy(computingFunction);
     }
 diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java
index 5f9a90e1748ee..0277762b0347c 100644
--- a/src/java.base/share/classes/java/util/List.java
+++ b/src/java.base/share/classes/java/util/List.java
@@ -1204,20 +1204,29 @@ static <E> List<E> copyOf(Collection<? extends E> coll) {
      * provided {@code computingFunction} when they are first accessed
      * (e.g., via {@linkplain List#get(int) List::get}).
      * <p>
-     * The provided computing function is guaranteed to be successfully
+     * The provided computing function is guaranteed to be
      * 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 the computing function completes abnormally.
      * <p>
-     * If invoking the provided computing function throws an exception, it is rethrown
-     * to the initial caller and no value for the element is recorded.
+     * If evaluation of the computing function throws an unchecked exception (for an
+     * index), the lazy element is not initialized but instead transitions to an error
+     * state. Subsequent {@linkplain List#get(int) List::get} calls for the same index
+     * throw {@linkplain NoSuchElementException} without ever invoking the computing
+     * function.
+     * <p>
+     * All failures are handled in this way. Here are two special cases that cause
+     * unchecked exceptions to be thrown:
      * <p>
      * If the provided computing function returns {@code null},
-     * a {@linkplain NullPointerException} will be thrown. Hence, just like other
+     * a {@linkplain NullPointerException} will be wrapped. Hence, just like other
      * unmodifiable lists created via the {@code List::of} factories, a lazy list
      * cannot contain {@code null} elements. Clients that want to use nullable elements
      * can wrap elements into an {@linkplain Optional} holder.
      * <p>
+     * If the computing function recursively invokes itself (for the same index) via the
+     * lazy list, an {@linkplain IllegalStateException} is wrapped.
+     * <p>
      * The elements of any {@link List#subList(int, int) subList()} or
      * {@link List#reversed()} views of the returned list are also lazily computed.
      * <p>
@@ -1232,17 +1241,44 @@ static <E> List<E> copyOf(Collection<? extends E> coll) {
      * {@linkplain Object#equals(Object) equals()},
      * {@linkplain Object#hashCode() hashCode()}, and
      * {@linkplain Object#toString() toString()} methods may trigger initialization of
-     * one or more lazy elements.
+     * one or more lazy elements. If initialization fails for at least one element,
+     * the {@linkplain Object Object methods} may throw {@linkplain NoSuchElementException}.
      * <p>
      * The returned lazy list strongly references its computing
      * function used to compute elements at least as long as there are uninitialized
      * elements.
      * <p>
      * The returned List is <em>not</em> {@linkplain Serializable}.
+     * <p>
+     * The returned {@code List<E>} can be thought of as a list backed by a
+     * {@code List<LazyConstant<E>>} field and where the {@linkplain List#get(int)}
+     * operation is equivalent to:
+     * {@snippet lang = java:
+     * class LazyList<E> extends AbstractList<E> {
+     *
+     *     private final List<LazyConstant<E>> backingList;
+     *
+     *     public LazyList(int size, IntFunction<E> computingFunction) {
+     *         this.backingList = IntStream.range(0, size)
+     *                 .mapToObj(i -> LazyConstant.of(() -> computingFunction.apply(i)))
+     *                 .toList();
+     *     }
+     *
+     *     @Override
+     *     public E get(int index) {
+     *         return backingList.get(index).get();
+     *     }
+     * }
+     *}
+     * Except, performance and storage efficiency might be better.
+     * <p>
+     * Elements in the returned list are eligible for certain performance optimizations
+     * such as <em>constant folding</em> as described in
+     * {@linkplain LazyConstant##performance LazyConstant}.
      *
-     * @implNote  after all elements have been initialized successfully, the computing
-     *            function is no longer strongly referenced and becomes eligible for
-     *            garbage collection.
+     * @implNote  after all elements have been initialized successfully or transioned to
+     *            an error state, the computing function is no longer strongly referenced
+     *            and becomes eligible for garbage collection.
      *
      * @param size              the size of the returned lazy list
      * @param computingFunction to invoke whenever an element is first accessed
diff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java
index fa16fb89050ac..7a2afbf792c99 100644
--- a/src/java.base/share/classes/java/util/Map.java
+++ b/src/java.base/share/classes/java/util/Map.java
@@ -1759,20 +1759,28 @@ static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) {
      * provided {@code computingFunction} when they are first accessed
      * (e.g., via {@linkplain Map#get(Object) Map::get}).
      * <p>
-     * The provided computing function is guaranteed to be successfully invoked
+     * The provided computing function is guaranteed to be invoked
      * at most once per key, even in a multi-threaded environment. Competing
-     * threads accessing a value already under computation will block until an element
+     * threads accessing a value already under computation will block until a value
      * is computed or the computing function completes abnormally.
      * <p>
-     * If invoking the provided computing function throws an exception, it
-     * is rethrown to the initial caller and no value associated with the provided key
-     * is recorded.
+     * If evaluation of the computing function throws an unchecked exception (for a
+     * key), the lazy value is not initialized but instead transitions to an error
+     * state. Subsequent {@linkplain Map#get(Object) Map::get} calls for the same key
+     * throw {@linkplain NoSuchElementException} without ever invoking the computing
+     * function.
+     * <p>
+     * All failures are handled in this way. Here are two special cases that cause
+     * unchecked exceptions to be thrown:
      * <p>
      * If the provided computing function returns {@code null},
-     * a {@linkplain NullPointerException} will be thrown. Hence, just like other
+     * a {@linkplain NullPointerException} will be wrapped. Hence, just like other
      * unmodifiable maps created via the {@code Map::of} factories, a lazy map
-     * cannot contain {@code null} values. Clients that want to use nullable values can
-     * wrap values into an {@linkplain Optional} holder.
+     * cannot contain {@code null} values. Clients that want to use nullable values
+     * can wrap values into an {@linkplain Optional} holder.
+     * <p>
+     * If the computing function recursively invokes itself (for the same key) via the
+     * lazy map, an {@linkplain IllegalStateException} is wrapped.
      * <p>
      * The values of any {@link Map#values()} or {@link Map#entrySet()} views of
      * the returned map are also lazily computed.
@@ -1785,17 +1793,55 @@ static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) {
      * {@linkplain Object#equals(Object) equals()},
      * {@linkplain Object#hashCode() hashCode()}, and
      * {@linkplain Object#toString() toString()} methods may trigger initialization of
-     * one or more lazy elements.
+     * one or more lazy values.  If initialization fails for at least one value,
+     * the {@linkplain Object Object methods} may throw {@linkplain NoSuchElementException}.
      * <p>
      * The returned lazy map strongly references its underlying
      * computing function used to compute values at least as long as there are
      * uncomputed values.
      * <p>
      * The returned Map is <em>not</em> {@linkplain Serializable}.
+     * <p>
+     * If the provided Set of {@code keys} is subsequently modified, the returned Map will
+     * not reflect such modifications.
+     * <p>
+     * The Set of {@code keys} must use {@linkplain Set#equals(Object) equals()} as its
+     * equivalence relation, or its comparison method must be consistent with equals,
+     * otherwise the behavior is unspecified.
+     * <p>
+     * The returned {@code Map<K, V>} can be thought of as a map backed by a
+     * {@code Map<K, LazyConstant<V>>} field and where the {@linkplain Map#get(Object)}
+     * operation is equivalent to:
+     * {@snippet lang = java:
+     * class LazyMap<K, V> extends AbstractMap<K, V> {
+     *
+     *     private final Map<K, LazyConstant<V>> backingMap;
+     *
+     *     public LazyMap(Set<K> keys, Function<K, V> computingFunction) {
+     *         this.backingMap = keys.stream()
+     *                 .collect(Collectors.toUnmodifiableMap(
+     *                         Function.identity(),
+     *                         k -> LazyConstant.of(() -> computingFunction.apply(k))));
+     *     }
+     *
+     *     @Override
+     *     public V get(Object key) {
+     *         var lazyConstant = backingMap.get(key);
+     *         return lazyConstant == null
+     *                 ? null
+     *                 : lazyConstant.get();
+     *     }
+     * }
+     *}
+     * Except, performance and storage efficiency might be better.
+     * <p>
+     * Values in the returned map are eligible for certain performance optimizations
+     * such as <em>constant folding</em> as described in
+     * {@linkplain LazyConstant##performance LazyConstant}.
      *
-     * @implNote  after all values have been initialized successfully, the computing
-     *            function is no longer strongly referenced and becomes eligible for
-     *            garbage collection.
+     * @implNote  after all valuess have been initialized successfully or transioned to
+     *            an error state, the computing function is no longer strongly referenced
+     *            and becomes eligible for garbage collection.
      *
      * @param keys              the (non-null) keys in the returned computed map
      * @param computingFunction to invoke whenever an associated value is first accessed
diff --git a/src/java.base/share/classes/java/util/Set.java b/src/java.base/share/classes/java/util/Set.java
index 5ce3bf04c7c48..6b508846e7af7 100644
--- a/src/java.base/share/classes/java/util/Set.java
+++ b/src/java.base/share/classes/java/util/Set.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,11 @@
 
 package java.util;
 
+import jdk.internal.javac.PreviewFeature;
+
+import java.io.Serializable;
+import java.util.function.Predicate;
+
 /**
  * A collection that contains no duplicate elements.  More formally, sets
  * contain no pair of elements {@code e1} and {@code e2} such that
@@ -77,7 +82,7 @@
  * Set to behave inconsistently or its contents to appear to change.
  * <li>They disallow {@code null} elements. Attempts to create them with
  * {@code null} elements result in {@code NullPointerException}.
- * <li>They are serializable if all elements are serializable.
+ * <li>Unless otherwise specified, they are serializable if all elements are serializable.
  * <li>They reject duplicate elements at creation time. Duplicate elements
  * passed to a static factory method result in {@code IllegalArgumentException}.
  * <li>The iteration order of set elements is unspecified and is subject to change.
@@ -734,4 +739,146 @@ static <E> Set<E> copyOf(Collection<? extends E> coll) {
             return (Set<E>)Set.of(new HashSet<>(coll).toArray());
         }
     }
+
+    /**
+     * {@return a new lazily computed set whose logical membership for each provided
+     *          {@code elementCandidates} is computed via the provided
+     *          {@code computingFunction} on demand}
+     * <p>
+     * In the following, the term <em>membership status</em> means whether an element is a
+     * logical member or a non-member. The returned set is an
+     * {@linkplain Collection##unmodifiable unmodifiable} set whose element candidates are
+     * known at construction. The set's element membership statuses are lazily computed
+     * via the provided {@code computingFunction} when first accessed (e.g., via
+     * {@linkplain Set#contains(Object) Set::contains}). Once the membership status has
+     * been successfully computed for an element candidate, the associated membership
+     * status is initialized (i.e., either as <em>a logical member</em> or as
+     * <em>a logical non-member</em>).
+     * <p>
+     * The provided computing function is guaranteed to be invoked
+     * at most once per element candidate, even in a multi-threaded environment. Competing
+     * threads accessing an element candidate already under membership status computation
+     * will block until the membership status of the element candidate is computed or the
+     * computing function completes abnormally.
+     * <p>
+     * If evaluation of the computing function throws an unchecked exception (for a
+     * membership candidate), the lazy membership status is not initialized but instead
+     * transitions to an error state. Subsequent {@linkplain Set#contains(Object)} Set::contains}
+     * calls for the same membership candidate throw {@linkplain NoSuchElementException}
+     * without ever invoking the computing function.
+     * <p>
+     * All failures are handled in this way. Here is a special case that causes
+     * unchecked exceptions to be thrown:
+     * <p>
+     * If the computing function recursively invokes itself (for the same membership
+     * candidate) via the lazy set, an {@linkplain IllegalStateException} is wrapped.
+     *
+     * The returned set's {@linkplain Object Object methods};
+     * {@linkplain Object#equals(Object) equals()},
+     * {@linkplain Object#hashCode() hashCode()}, and
+     * {@linkplain Object#toString() toString()} methods may trigger initialization of
+     * one or more lazy elements. If initialization fails for at least one element,
+     * the {@linkplain Object Object methods} may throw {@linkplain NoSuchElementException}.
+     * <p>
+     * The returned lazy set strongly references its underlying
+     * computing function used to compute membership status at least as long as there are
+     * uncomputed element candidates.
+     * <p>
+     * The returned Set is <em>not</em> {@linkplain Serializable}.
+     * <p>
+     * Here is an example involving an application that manages various configurable
+     * options -- commonly referred to as "switches" -- that control its behavior. The
+     * state of these switches can be determined through the command line, a configuration
+     * file, or even a database connection. By using a lazy set, we ensure that the states
+     * of these switches are evaluated only once. Once computed, the results are eligible
+     * for constant folding by the JVM:
+     * {@snippet lang = java:
+     * class Application {
+     *
+     *     enum Option{VERBOSE, DRY_RUN, STRICT}
+     *
+     *     // Lazily initialized Set of Options
+     *     static final Set<Option> OPTIONS =
+     *             Set.ofLazy(EnumSet.allOf(Option.class), Application::isEnabled);
+     *
+     *     // Return true when the given Option is enabled
+     *     private static boolean isEnabled(Option option) {
+     *         // Parse command line, read configuration file, load database
+     *         ...
+     *     }
+     *
+     *     public static void process() {
+     *         if (OPTIONS.contains(Option.DRY_RUN)) {
+     *             // Skip processing in DRY_RUN mode
+     *             return;
+     *         }
+     *         // Actual processing logic
+     *     }
+     *
+     * }
+     * }
+     * <p>
+     * If the provided Set of {@code elementCandidates} is subsequently modified, the
+     * returned Set will not reflect such modifications.
+     * <p>
+     * The Set of {@code elementCandidates} must use
+     * {@linkplain Set#equals(Object) equals()} as its equivalence relation, or its
+     * comparison method must be consistent with {@code equals()}, otherwise the behavior
+     * is unspecified.
+     * <p>
+     * The returned {@code Set<E>} can be thought of as a set backed by a
+     * {@code Map<E, LazyConstant<Boolean>>} field and where the {@linkplain Set#contains(Object)}
+     * operation is equivalent to:
+     * {@snippet lang = java:
+     * class LazySet<E> extends AbstractCollection<E> implements Set<E> {
+     *
+     *     private final Map<E, LazyConstant<Boolean>> backingMap;
+     *
+     *     public LazySet(Set<E> elementCandidates, Predicate<E> computingFunction) {
+     *         this.backingMap = elementCandidates.stream()
+     *                 .collect(Collectors.toUnmodifiableMap(
+     *                         Function.identity(),
+     *                         k -> LazyConstant.of(() -> computingFunction.test(k))));
+     *     }
+     *
+     *     @Override
+     *     public boolean contains(Object o) {
+     *         var lazyConstant = backingMap.get(o);
+     *         return lazyConstant == null
+     *                 ? false
+     *                 : lazyConstant.get();
+     *     }
+     * }
+     *}
+     * Except, performance and storage efficiency might be better.
+     * <p>
+     * Elements in the returned set are eligible for certain performance optimizations
+     * such as <em>constant folding</em> as described in
+     * {@linkplain LazyConstant##performance LazyConstant}.
+     *
+     * @implNote  after all element membership statuses have been initialized
+     *            successfully or transioned to an error state, the computing function is
+     *            no longer strongly referenced and becomes eligible for garbage
+     *            collection.
+     *
+     * @param elementCandidates the (non-null) element candidates to be evaluated
+     * @param computingFunction to invoke whenever the membership status of an element
+     *                          candidate is first computed
+     * @param <E>               the type of elements maintained by the returned set
+     * @throws NullPointerException if the provided set of {@code elementCandidates} is
+     *                              {@code null}, if the set of {@code elementCandidates}
+     *                              contains a {@code null} element, or if the provided
+     *                              {@code computingFunction} is {@code null}
+     *
+     * @see LazyConstant
+     * @since 27
+     */
+    @PreviewFeature(feature = PreviewFeature.Feature.LAZY_CONSTANTS)
+    static <E> Set<E> ofLazy(Set<? extends E> elementCandidates,
+                             Predicate<? super E> computingFunction) {
+        Objects.requireNonNull(elementCandidates);
+        Objects.requireNonNull(computingFunction);
+        return LazyCollections.ofLazySet(elementCandidates, computingFunction);
+    }
+
 }
