本文详细阐述在java中如何利用`supplier`接口和`stream.of()`方法,从一组固定表达式创建惰性求值的流。通过将每个表达式封装为`supplier`实例,并构建`stream
在Java 8及更高版本中,Stream API为数据处理提供了强大而灵活的工具。然而,当我们需要从一系列固定表达式创建流时,常见的Stream.of(expression1(), expression2(), ...)方法会立即执行这些表达式并将其结果作为流的元素。对于计算成本高昂或资源密集型的表达式,这种立即求值的行为可能导致不必要的性能开销或资源浪费。为了实现惰性求值,即仅在需要时才执行表达式,我们可以巧妙地结合Supplier接口。
java.util.function.Supplier
要从固定数量的表达式生成一个惰性流,我们不直接将表达式的结果放入流中,而是将封装了这些表达式的Supplier实例放入流中。Stream.of()方法可以接受任意类型的对象作为其元素,因此它可以接受Supplier实例。
假设我们有三个表达式expression1()、expression2()和expression3(),它们都返回MyClass类型的对象。我们可以这样构建一个Stream
import java.util.function.Supplier;
import java.util.stream.Stream;
public class LazyStreamExample {
// 假设MyClass及其表达式
static class MyClass {
private String id;
public MyClass(String id) {
this.id = id;
System.out.println("MyClass " + id + " created."); // 模拟耗时操作
}
public String getId() {
return id;
}
}
// 模拟耗时表达式
private static MyClass expression1() {
return new MyClass("One");
}
private static MyClass expression2() {
return new MyClass("Two");
}
private static MyClass expression3() {
return new MyClass("Three");
}
public static void main(String[] args) {
System.out.println("--- 开始构建惰性流 ---");
Stream> lazyStream = Stream.of(
() -> expression1(),
() -> expression2(),
() -> expression3()
);
System.out.println("--- 惰性流构建完成,表达式尚未执行 ---");
// 此时,控制台不会输出 "MyClass One created." 等信息,
// 因为expression1()等方法尚未被调用。
}
} 在上述代码中,当Stream.of()被调用时,它仅仅创建了三个Supplier对象,并把它们作为流的元素。expression1()、expression2()和expression3()这些方法本身并没有被执行,因此其内部的耗时操作(例如MyClass的构造函数)也未被
触发。
一旦我们有了Stream
import java.util.function.Supplier;
import java.util.stream.Stream;
public class LazyStreamExample {
// ... (MyClass 和 expression1/2/3 方法同上) ...
public static void main(String[] args) {
System.out.println("--- 开始构建惰性流 ---");
Stream> lazyStream = Stream.of(
() -> expression1(),
() -> expression2(),
() -> expression3()
);
System.out.println("--- 惰性流构建完成,表达式尚未执行 ---");
// 示例:查找第一个满足条件的MyClass对象
System.out.println("\n--- 开始处理惰性流 ---");
MyClass result = lazyStream.map(Supplier::get) // 在此处调用Supplier::get,触发表达式执行
.filter(myObj -> {
System.out.println("过滤对象: " + myObj.getId());
return myObj.getId().equals("Two"); // 假设条件
})
.findFirst()
.orElse(null); // 或者orElseThrow()
if (result != null) {
System.out.println("\n--- 找到结果: " + result.getId() + " ---");
} else {
System.out.println("\n--- 未找到满足条件的结果 ---");
}
System.out.println("\n--- 再次处理惰性流,验证惰性特性 ---");
// 注意:Stream是单次消费的,这里仅为演示,实际应用中需重新构建流
// 假设我们重新构建一个流用于演示
Stream> anotherLazyStream = Stream.of(
() -> expression1(),
() -> expression2(),
() -> expression3()
);
anotherLazyStream.map(Supplier::get)
.filter(myObj -> {
System.out.println("再次过滤对象: " + myObj.getId());
return myObj.getId().equals("Three");
})
.findFirst();
System.out.println("--- 再次处理完成 ---");
}
} 运行上述代码,你将观察到以下行为:
优势:
注意事项:
通过将表达式封装在Supplier中并构建Stream