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

Will stream().limit() optimize execution if total size of list is less than 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 是否足够聪明,可以理解列表大小小于限制? 还是会盲目遍历列表中的每个数字,直到到达列表末尾或达到限制?

stream().limit(5) 不是终端操作,所以你不能限制列表认为我已经完成了 limit(),它会将限制值存储在 limitedlist 中。即使您使用 collect() 您仍然无法实现限制列表并将其存储在 limitedlist 中,因为会发生类型不匹配。

你需要使用 .collect() 作为终端操作,然后使用 Collectors.toList() 将其添加到 limitedlist ,不要尝试在同一行打印它,因为它会抛出错误说 类型不匹配

流操作是延迟执行的,所以 Java 不会抛出错误,因为它不知道列表的限制,所以如果限制大小超过列表的实际大小,那么它将 return 所有元素的最大 大小。

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);
    }

case 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: 流不是数据结构,流操作是延迟执行的。

我们来试试吧。这是您的代码版本,其中列表的总大小小于限制(如您的标题所述):

    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 returns 一个空列表。同样,没有什么可以优化的。

不,它不会优化执行(即使在 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

因此,它必须遍历整个流才能找出确切的大小。