如何在Java中从固定数量的表达式生成惰性流?
惰性版Stream.of实现方案
问题描述
想要实现和Stream.of()相同的功能,但要求惰性执行——即传入的表达式不会在创建流时立即求值,而是等到流被终端操作触发时才执行。
原有的Stream.of()写法(会立即执行所有表达式):
Stream<MyClass> s = Stream.of( expression1(), expression2(), expression3(), ... );
目前已实现的方式(用Supplier列表存储延迟计算逻辑):
List<Supplier<MyClass>> s = Arrays.asList( ()->expression1(), ()->expression2(), ()->expression3(), ... );
现在希望直接通过流来实现,同时需要解决Supplier作为流元素时的重复执行问题(比如流多次执行终端操作时,Supplier会被重复调用,导致表达式重复执行)。
解决方案
1. 基础惰性流实现
可以将Supplier直接包装进流,通过map触发求值,默认情况下流每次终端操作都会重新执行Supplier逻辑:
Stream<Supplier<MyClass>> supplierStream = Stream.of( () -> expression1(), () -> expression2(), () -> expression3() ); // 仅当终端操作执行时,才会触发对应表达式的求值 Stream<MyClass> lazyStream = supplierStream.map(Supplier::get);
2. 解决重复执行问题(缓存求值结果)
如果需要避免表达式被重复执行,可以给每个Supplier添加缓存逻辑,确保每个表达式只执行一次。自定义带缓存的包装类:
class CachedSupplier<T> implements Supplier<T> { private final Supplier<T> delegate; private volatile T value; private boolean initialized; public CachedSupplier(Supplier<T> delegate) { this.delegate = delegate; } @Override public T get() { if (!initialized) { synchronized (this) { if (!initialized) { value = delegate.get(); initialized = true; } } } return value; } }
用该类创建惰性流,即可保证每个表达式仅执行一次:
Stream<MyClass> lazyCachedStream = Stream.of( new CachedSupplier<>(() -> expression1()), new CachedSupplier<>(() -> expression2()), new CachedSupplier<>(() -> expression3()) ).map(Supplier::get);
3. 自定义惰性版of方法(更简洁)
封装工具方法,直接生成带缓存的惰性流,使用方式和Stream.of()一致:
public static <T> Stream<T> lazyOf(Supplier<T>... suppliers) { return Arrays.stream(suppliers) .map(CachedSupplier::new) .map(Supplier::get); }
调用示例:
Stream<MyClass> s = lazyOf( () -> expression1(), () -> expression2(), () -> expression3() );
内容的提问来源于stack exchange,提问作者Dims
相关产品推荐
相关产品推荐

