如果limit
的值大于list
的大小,java是否会优化而不执行此代码?
List<Long> someList = Arrays.asList(1L, 2L, 3L, 4L, 5L);
int limit = 5;
List<Long> limitedList = someList.stream().limit(limit).collect(Collectors.toList());
假设limit = 1000000
和someList.size() = 99999
。
现在,java会足够聪明地了解列表大小小于限制吗? 还是会盲目地遍历列表中的每个数字,直到到达列表末尾或达到限制?
答案 0 :(得分:2)
否,它不会优化执行(即使在JDK 11中也是如此)。
让我们尝试最简单的终端操作(count
):
var someList = Arrays.asList(1, 2, 3, 4, 5);
var limit = 10_000;
System.out.println(someList
.stream()
.peek(System.out::println)
.limit(limit)
.count());
程序将打印:
1
2
3
4
5
5
因此,它必须遍历整个流以找出确切的大小。
答案 1 :(得分:0)
stream().limit(5)
不是终端操作,因此您不能以我已经完成limit()
的方式来限制列表,它将把有限的值存储在limitedlist
中。即使您使用collect()
,也仍然无法达到限制列表并将其存储在limitedlist
中的目的,因为类型不匹配会发生。
您需要使用.collect()
作为终端操作,然后使用Collectors.toList()
将其添加到limitedlist
中,请勿尝试在同一行中打印它,否则会抛出错误,提示< strong>类型不匹配。
流操作是延迟执行的,因此Java将不抛出错误,因为它不知道列表的限制,因此,如果限制大小超出列表的实际大小,则它将返回 maximum < / strong>大小以及所有元素。
List<Long> someList = Arrays.asList(1L, 2L, 3L, 4L, 5L);
List<Long> limitedList = someList.stream().limit(5).collect(Collectors.toList());
for(long aa:limitedList)
{
System.out.println(aa);
}
情况2: [[limit
操作大小超出了somelist
的实际大小。 ]
List<Long> someList = Arrays.asList(1L, 2L, 3L, 4L, 5L);
List<Long> limitedList = someList.stream().limit(7).collect(Collectors.toList());
for(long aa:limitedList)
{
System.out.println(aa);
}
输出:结果将是整个somelist
元素。
PS: 流不是数据结构,流操作被延迟执行。
答案 2 :(得分:0)
尝试一下。这是代码的一个版本,其中列表的总大小小于限制(如标题所示):
List<Long> someList = Arrays.asList(7L, 2L, 11L, 5L);
int limit = 6;
List<Long> limitedList = someList.stream().skip(limit).collect(Collectors.toList());
System.out.println(limitedList);
输出为:
[7,2,11,5]
所以代码确实执行了。将流限制为6个元素只会设置最大如果列表中可用的元素更少,则流很乐意使用更少的元素执行。因此,实际上没有什么要优化的。
您可能想记住流是懒惰地执行的:元素是从终端操作(此处为toList
)中拉出的,通常直到没有其他元素为止。因此toList
向limit
请求元素。 limit
将继续提供元素,直到 达到限制(6)或,否则它将无法从流中获取更多元素(列表已耗尽)。它必须。如果我们认为它不能覆盖所有要素,那么它将无法产生正确的结果。
延迟执行也是注释表示流无法执行的原因之一。在问题的第一个版本中,您没有终端操作(例如collect(Collectors.toList());
),因此不会从limit
中提取任何元素(您可以称其为优化?)您已添加了终端现在操作。
您可能会想到skip
吗?让我们尝试更改上面的中间代码行:
List<Long> limitedList = someList.stream().skip(6).collect(Collectors.toList());
[]
这里toList
向skip
请求元素。 skip
首先尝试从列表中获取6个元素。 4之后,该列表已用尽。此时skip
告诉toList
没有更多的元素,因此toList
返回一个空列表。同样,实际上没有什么要优化的。