如果列表的总大小小于限制,stream()。limit()是否会优化执行?

时间:2019-01-15 03:16:43

标签: java java-8 java-stream limit

如果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 = 1000000someList.size() = 99999

现在,java会足够聪明地了解列表大小小于限制吗? 还是会盲目地遍历列表中的每个数字,直到到达列表末尾或达到限制?

3 个答案:

答案 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)中拉出的,通常直到没有其他元素为止。因此toListlimit请求元素。 limit将继续提供元素,直到 达到限制(6),否则它将无法从流中获取更多元素(列表已耗尽)。它必须。如果我们认为它不能覆盖所有要素,那么它将无法产生正确的结果。

延迟执行也是注释表示流无法执行的原因之一。在问题的第一个版本中,您没有终端操作(例如collect(Collectors.toList());),因此不会从limit中提取任何元素(您可以称其为优化?)您已添加了终端现在操作。

您可能会想到skip吗?让我们尝试更改上面的中间代码行:

    List<Long> limitedList = someList.stream().skip(6).collect(Collectors.toList());
  

[]

这里toListskip请求元素。 skip首先尝试从列表中获取6个元素。 4之后,该列表已用尽。此时skip告诉toList没有更多的元素,因此toList返回一个空列表。同样,实际上没有什么要优化的。