Java 8流的toArray和size参数

我想知道stream()。toArray [x – > new Integer [x]]如何知道来自哪个数组的大小? 我写了一个片段,其中我创建了一个大小为4的整数列表并过滤了值,它创建了一个长度为过滤流的数组,我无法看到任何方法来获取流的大小。

List intList = new ArrayList(); intList.add(1); intList.add(2); intList.add(3); intList.add(4); Integer[] array = intList.stream() .filter(x -> x > 2) .toArray(x -> { System.out.println("x --> " + x); return new Integer[x]; }); System.out.println("array length: " + array.length); 

上述代码的输出:

 x --> 2 array length: 2 

最初,片段就像

 Integer[] array = intList.stream() .filter(x -> x > 2) .toArray(x -> new Integer[x]); 

只是为了理解它传递的x的值,我必须改变它以在lambda中打印x

当然,这取决于实现。 对于某些流,如果源具有已知大小且不涉及大小改变中间操作,则大小是可预测的。 由于您使用的是filter操作,因此不适用,但是,根据未过滤的计数,存在估计大小。

现在,Stream实现只是分配一个临时缓冲区,使用估计的大小或默认大小,并在必要时支持增加容量,并在最后一步将数据复制到由函数创建的目标数组中。

可以通过提供的函数创建中间缓冲区,这就是文档说明“… 使用提供的生成器函数分配返回的数组,以及分区执行或resize可能需要的任何其他数组 ”的原因。我依稀记得在早期版本中看到过这种行为。 但是,当前实现只是在“spined buffer”中使用Object[]数组(或Object[][]进行中间存储,并仅使用提供的函数来创建最终数组。 因此,在给定此特定JRE实现的情况下,您无法使用该函数观察中间数组的创建。

问题是:这是终端操作。 它最终发生在流处理时:意思是 – 当时知道“最终”计数; 因为没有更多的操作可以删除/添加流的值!

只需查看toArray的javas stream文档。


  A[] toArray(IntFunction generator) 

返回一个包含此流元素的数组,使用提供的生成器函数分配返回的数组,以及分区执行或resize可能需要的任何其他数组。

这是终端操作。

API注意: 生成器函数采用整数,该大小是所需数组的大小,并生成所需大小的数组。 这可以用数组构造函数引用简洁地表达


因此, toArray确实为您提供了所需的数组大小作为参数,并且您负责分配正确大小的数组,至少在使用此方法时。 该方法是终端操作。 因此,大小计算是在Stream API的内部完成的。

恕我直言,如果你为filter和toArray命名不同的lambda参数,最好掌握。

 Integer[] array = intList.stream() .filter(myint -> myint > 2) .toArray(desiredArraySize -> new Integer[desiredArraySize]);