我最近阅读了很多关于 Java 8 流的文章,还有几篇关于使用 Java 8 流进行延迟加载的文章:here and over here。我似乎无法摆脱延迟加载完全没用的感觉(或者充其量只是提供零性能价值的次要语法便利)。
我们以这段代码为例:
int[] myInts = new int[]{1,2,3,5,8,13,21};
IntStream myIntStream = IntStream.of(myInts);
int[] myChangedArray = myIntStream
.peek(n -> System.out.println("About to square: " + n))
.map(n -> (int)Math.pow(n, 2))
.peek(n -> System.out.println("Done squaring, result: " + n))
.toArray();
这将登录控制台,因为terminal operation在这种情况下toArray()调用的是 ,而我们的流是惰性的,仅在调用终端操作时才执行。当然我也可以这样做:
IntStream myChangedInts = myIntStream
.peek(n -> System.out.println("About to square: " + n))
.map(n -> (int)Math.pow(n, 2))
.peek(n -> System.out.println("Done squaring, result: " + n));
并且不会打印任何内容,因为地图没有发生,因为我不需要数据。直到我称之为:
int[] myChangedArray = myChangedInts.toArray();
瞧,我得到了映射数据和控制台日志。除了我认为它的好处为零。我意识到我可以在调用 之前很久就定义过滤器代码toArray(),并且我可以传递这个“未真正过滤的流),但那又怎样?这是唯一的好处吗?
这些文章似乎暗示有与懒惰相关的性能提升,例如:
在Java 8 Streams API中,中间操作是惰性的,并且对其内部处理模型进行了优化,使其能够高性能地处理大量数据。
和
Java 8 Streams API 在短路操作的帮助下优化了流处理。短路方法在满足条件后立即结束流处理。用正常的话短路操作,一旦条件满足就会中断所有中间操作,位于管道之前。一些中间和终端操作具有这种行为。
从字面上看,这听起来像是跳出一个循环,根本与懒惰无关。
最后,在第二篇文章中有这句令人费解的台词:
惰性操作实现效率。这是一种不处理陈旧数据的方法。在逐渐消耗输入数据而不是预先拥有完整的元素集的情况下,延迟操作可能很有用。例如,考虑使用 Stream#generate(Supplier<T>) 创建无限流并且提供的供应商函数逐渐从远程服务器接收数据的情况。在这种情况下,服务器调用只会在需要时在终端操作中进行。
不处理陈旧数据?什么?延迟加载如何防止某人处理陈旧数据?
TLDR:除了能够在以后运行 filter/map/reduce/whatever 操作(这提供零性能优势)之外,延迟加载还有什么好处吗?
如果是这样,现实世界的用例是什么?
Helenr
陪伴而非守候
湖上湖
相关分类