如果列表的总大小小于限制,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 = 1000000
和 someList.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
因此,它必须遍历整个流才能找出确切的大小。
如果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 是否足够聪明,可以理解列表大小小于限制? 还是会盲目遍历列表中的每个数字,直到到达列表末尾或达到限制?
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
因此,它必须遍历整个流才能找出确切的大小。