Created
October 28, 2025 03:37
-
-
Save Quackster/32fd7487843f77ee63357446e1420d08 to your computer and use it in GitHub Desktop.
Java Lazily Load Library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Value.java | |
| import java.util.concurrent.CompletableFuture; | |
| import java.util.function.Function; | |
| import java.util.function.Supplier; | |
| /** | |
| * A container that holds a value and supports both eager and lazy transformations. | |
| * Provides synchronous and asynchronous computation capabilities. | |
| * | |
| * @param <T> the type of the contained value | |
| */ | |
| public class Value<T> { | |
| private final T value; | |
| /** | |
| * Creates a new Value with the given value. | |
| * | |
| * @param value the value to wrap | |
| */ | |
| public Value(T value) { | |
| this.value = value; | |
| } | |
| /** | |
| * Returns the contained value. | |
| * | |
| * @return the value | |
| */ | |
| public T value() { | |
| return value; | |
| } | |
| /** | |
| * Applies a transformation function eagerly and returns a new Value. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return a new Value containing the transformed value | |
| */ | |
| public <R> Value<R> apply(Function<T, R> mapper) { | |
| return new Value<>(mapper.apply(value)); | |
| } | |
| /** | |
| * Applies a transformation function lazily and returns a LazyValue. | |
| * The computation is deferred until value() is called on the LazyValue. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return a LazyValue that will compute the result when accessed | |
| */ | |
| public <R> LazyValue<R> applyLazy(Function<T, R> mapper) { | |
| return new LazyValue<>(() -> mapper.apply(value)); | |
| } | |
| /** | |
| * Applies a transformation function asynchronously using CompletableFuture. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return an AsyncValue wrapping a CompletableFuture | |
| */ | |
| public <R> AsyncValue<R> applyAsync(Function<T, R> mapper) { | |
| CompletableFuture<R> future = CompletableFuture.supplyAsync(() -> mapper.apply(value)); | |
| return new AsyncValue<>(future); | |
| } | |
| @Override | |
| public String toString() { | |
| return "Value{" + value + "}"; | |
| } | |
| } | |
| // LazyValue.java | |
| /** | |
| * A lazily-evaluated value that computes its result only when accessed. | |
| * Once computed, the result is cached for subsequent accesses. | |
| * | |
| * @param <T> the type of the contained value | |
| */ | |
| class LazyValue<T> { | |
| private final Supplier<T> supplier; | |
| private volatile T cachedValue; | |
| private volatile boolean computed = false; | |
| /** | |
| * Creates a new LazyValue with the given supplier. | |
| * | |
| * @param supplier the supplier that computes the value | |
| */ | |
| public LazyValue(Supplier<T> supplier) { | |
| this.supplier = supplier; | |
| } | |
| /** | |
| * Gets the value, computing it if necessary. | |
| * The result is cached after the first computation. | |
| * | |
| * @return a Lazy wrapper containing the computed value | |
| */ | |
| public Lazy<T> value() { | |
| return new Lazy<>(this::get); | |
| } | |
| /** | |
| * Computes and returns the value, using cached result if available. | |
| * | |
| * @return the computed value | |
| */ | |
| private T get() { | |
| if (!computed) { | |
| synchronized (this) { | |
| if (!computed) { | |
| cachedValue = supplier.get(); | |
| computed = true; | |
| } | |
| } | |
| } | |
| return cachedValue; | |
| } | |
| /** | |
| * Applies a transformation function eagerly to the lazy value. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return a new Value containing the transformed result | |
| */ | |
| public <R> Value<R> apply(Function<T, R> mapper) { | |
| return new Value<>(mapper.apply(get())); | |
| } | |
| /** | |
| * Applies a transformation function lazily. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return a new LazyValue that chains the transformations | |
| */ | |
| public <R> LazyValue<R> applyLazy(Function<T, R> mapper) { | |
| return new LazyValue<>(() -> mapper.apply(get())); | |
| } | |
| /** | |
| * Applies a transformation function asynchronously. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return an AsyncValue wrapping a CompletableFuture | |
| */ | |
| public <R> AsyncValue<R> applyAsync(Function<T, R> mapper) { | |
| CompletableFuture<R> future = CompletableFuture.supplyAsync(() -> mapper.apply(get())); | |
| return new AsyncValue<>(future); | |
| } | |
| @Override | |
| public String toString() { | |
| return computed ? "LazyValue{computed=" + cachedValue + "}" : "LazyValue{not computed}"; | |
| } | |
| } | |
| // Lazy.java | |
| /** | |
| * A simple wrapper that provides lazy access to a value. | |
| * | |
| * @param <T> the type of the contained value | |
| */ | |
| class Lazy<T> { | |
| private final Supplier<T> supplier; | |
| public Lazy(Supplier<T> supplier) { | |
| this.supplier = supplier; | |
| } | |
| /** | |
| * Gets the value from the supplier. | |
| * | |
| * @return the value | |
| */ | |
| public T get() { | |
| return supplier.get(); | |
| } | |
| @Override | |
| public String toString() { | |
| return "Lazy{...}"; | |
| } | |
| } | |
| // AsyncValue.java | |
| /** | |
| * A value that is computed asynchronously using CompletableFuture. | |
| * | |
| * @param <T> the type of the contained value | |
| */ | |
| class AsyncValue<T> { | |
| private final CompletableFuture<T> future; | |
| /** | |
| * Creates a new AsyncValue wrapping a CompletableFuture. | |
| * | |
| * @param future the CompletableFuture to wrap | |
| */ | |
| public AsyncValue(CompletableFuture<T> future) { | |
| this.future = future; | |
| } | |
| /** | |
| * Returns the underlying CompletableFuture. | |
| * | |
| * @return the CompletableFuture | |
| */ | |
| public CompletableFuture<T> value() { | |
| return future; | |
| } | |
| /** | |
| * Applies a transformation function to the future result. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return a new AsyncValue with the transformed result | |
| */ | |
| public <R> AsyncValue<R> apply(Function<T, R> mapper) { | |
| return new AsyncValue<>(future.thenApply(mapper)); | |
| } | |
| /** | |
| * Applies a transformation function asynchronously to the future result. | |
| * | |
| * @param <R> the result type | |
| * @param mapper the transformation function | |
| * @return a new AsyncValue with the transformed result | |
| */ | |
| public <R> AsyncValue<R> applyAsync(Function<T, R> mapper) { | |
| return new AsyncValue<>(future.thenApplyAsync(mapper)); | |
| } | |
| /** | |
| * Blocks and gets the result from the CompletableFuture. | |
| * | |
| * @return the computed value | |
| */ | |
| public T get() { | |
| try { | |
| return future.get(); | |
| } catch (Exception e) { | |
| throw new RuntimeException("Failed to get async value", e); | |
| } | |
| } | |
| @Override | |
| public String toString() { | |
| return "AsyncValue{future=" + (future.isDone() ? "completed" : "pending") + "}"; | |
| } | |
| } | |
| // BoxExamples.java | |
| /** | |
| * Example usage of the lazy load library. | |
| */ | |
| public class BoxExamples { | |
| public static void main(String[] args) throws Exception { | |
| // Example 1: Eager evaluation | |
| Value<Integer> num = new Value<>(5); | |
| Value<Integer> doubled = num.apply(n -> n * 2); | |
| System.out.println("Doubled: " + doubled.value()); | |
| // Example 2: Lazy evaluation | |
| var doubled2 = num.applyLazy(n -> n * 2); | |
| System.out.println("Doubled2: " + doubled2.value().get()); | |
| // Example 3: Chaining on lazy value | |
| Value<Integer> doubled3 = doubled.apply(n -> n); | |
| System.out.println("Doubled3: " + doubled3.value()); | |
| // Example 4: Async evaluation | |
| System.out.println("\n--- Async Examples ---"); | |
| AsyncValue<Integer> asyncDoubled = num.applyAsync(n -> { | |
| System.out.println("Computing async..."); | |
| return n * 2; | |
| }); | |
| System.out.println("Result: " + asyncDoubled.value().get()); | |
| // Example 5: Chaining async operations | |
| AsyncValue<Integer> asyncChained = asyncDoubled | |
| .apply(n -> n + 10) | |
| .applyAsync(n -> n * 3); | |
| System.out.println("Chained async result: " + asyncChained.get()); | |
| // Example 6: Lazy chain | |
| System.out.println("\n--- Lazy Chain ---"); | |
| LazyValue<Integer> lazyChain = num.applyLazy(n -> { | |
| System.out.println("Step 1: " + n); | |
| return n * 2; | |
| }).applyLazy(n -> { | |
| System.out.println("Step 2: " + n); | |
| return n + 5; | |
| }); | |
| System.out.println("Before evaluation: " + lazyChain); | |
| System.out.println("Evaluated result: " + lazyChain.value().get()); | |
| System.out.println("After evaluation: " + lazyChain); | |
| // Example 7: Async with delay and callbacks | |
| System.out.println("\n--- Async with Delay and Callbacks ---"); | |
| System.out.println("Starting async operation at: " + System.currentTimeMillis()); | |
| Value<String> message = new Value<>("Hello"); | |
| AsyncValue<String> delayedAsync = message.applyAsync(msg -> { | |
| try { | |
| System.out.println("Processing started... (will take 2 seconds)"); | |
| Thread.sleep(2000); // 2 second delay | |
| return msg + " World!"; | |
| } catch (InterruptedException e) { | |
| throw new RuntimeException(e); | |
| } | |
| }); | |
| // Attach callbacks using CompletableFuture's thenAccept | |
| delayedAsync.value() | |
| .thenAccept(result -> { | |
| System.out.println("Callback 1 - Result received: " + result); | |
| System.out.println("Completed at: " + System.currentTimeMillis()); | |
| }) | |
| .thenRun(() -> System.out.println("Callback 2 - All done!")); | |
| System.out.println("Main thread continues immediately..."); | |
| // Chain more operations with delays | |
| AsyncValue<Integer> multiStep = new Value<>(1) | |
| .applyAsync(n -> { | |
| sleep(500); | |
| System.out.println("Step 1 complete: " + n); | |
| return n * 2; | |
| }) | |
| .applyAsync(n -> { | |
| sleep(500); | |
| System.out.println("Step 2 complete: " + n); | |
| return n + 10; | |
| }) | |
| .applyAsync(n -> { | |
| sleep(500); | |
| System.out.println("Step 3 complete: " + n); | |
| return n * 3; | |
| }); | |
| // Handle completion and errors | |
| multiStep.value() | |
| .whenComplete((result, error) -> { | |
| if (error != null) { | |
| System.out.println("Error occurred: " + error.getMessage()); | |
| } else { | |
| System.out.println("Final result: " + result); | |
| } | |
| }); | |
| // Wait for all async operations to complete | |
| Thread.sleep(3000); | |
| System.out.println("\n--- All operations completed ---"); | |
| } | |
| private static void sleep(long millis) { | |
| try { | |
| Thread.sleep(millis); | |
| } catch (InterruptedException e) { | |
| throw new RuntimeException(e); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment