这两种流创建方法之间是否存在显着差异(在性能或最佳实践方面)?
int[] arr2 = {1,2,3,4,5,6};
Arrays.stream(arr2)
.map((in)->in*2)
.mapToObj((in) -> new Integer(in))
.collect(Collectors.toCollection(()-> new ArrayList<>()));
Arrays.stream(arr2)
.map(in->in*2)
.boxed()
.collect(Collectors.toCollection(()-> new ArrayList<>()));
感谢 Stack Community 的回答,我可以添加一些插件来为新读者提出问题的完整性:
正如许多人指出的那样,
.boxed()
IntStream 方法定义为:
@Override
public final Stream<Integer> boxed() {
return mapToObj(Integer::valueOf);
}
基本上重新定义了以下哪一项更好的问题:
.mapToObj(in -> new Integer(in))
或
.mapToObj(in -> Integer.valueOf(in))
boxed()
使用Integer.valueOf
,它可以从缓存中检索一些
Integer
实例。
因此,您应该使用带有
boxed()
的版本(最好),或者使用 Integer.valueOf
而不是 new Integer()
。请注意,boxed()
实际上是 mapToObj(Integer::valueOf)
的简写。
第二个更好,因为在本例中它没有创建
Integer
对象。
如果装箱的值 p 是……一个介于 -128 和 127(含)之间的 int ……,则令 r1 和 r2 为 p 的任意两次装箱转换的结果。 r1 == r2 的情况总是如此。
一般来说,您不应该在包装类型上调用
new
,而应使用它们的 static
工厂方法 - 例如 Integer.valueOf
IntStream.boxed()
使用Integer.valueOf(int)
,这是Integer(int)
的优化版本*。
在内部,
boxed()
定义为 mapToObj(Integer::valueOf)
。
*此方法通常应优先于构造函数
使用,因为此方法可能通过缓存频繁请求的值来产生显着更好的空间和时间性能。Integer(int)
的JavadocInteger.valueOf(int)
就最佳实践而言,第二种方法更可取,因为当您想要对原始值进行装箱时,
boxed
正是为此目的而创建的,并且以尽可能最优化的方式实现,而mapToObj
虽然可以用于实现同样的事情,这不是惯用的方法。
此外,建议不要再使用原始包装类型构造函数,而应使用
valueOf
方法,这是因为这些构造函数已被弃用,而且与使用 valueOf
相比,它可以减少内存占用构造函数可以带来更好的性能。
第二个将有效地使用jvm的整数缓存,因此它在性能和最佳实践方面都会更好(不要实例化装箱类型,而是让vm为你做这件事)。
如果您将
new Integer(in)
更改为 Integer.valueOf(in)
,您可以模仿相同的行为
对于性能和最佳实践,我们应该选择
boxed()
而不是 mapToObj((in) -> new Integer(in))
。
性能:
参见下面的
boxed()
源代码(在抽象类IntPipeline<E_IN>
中,它实现了IntStream
,在package java.util.stream
中):
@Override
public final Stream<Integer> boxed() {
return mapToObj(Integer::valueOf);
}
所以它用
mapToObj()
来调用 Integer::valueOf
。请注意,通过重用缓存值,Integer::valueOf
比new Integer()
更高效,所以我们应该选择boxed()
。
最佳实践:
除了性能差异之外,使用
boxed()
我们写得更少,而且更容易阅读。
第二个更好,甚至可以在不使用
boxed()
作为 Java 自动框到使用 Integer.valueOf(int)
的整数的情况下缩短。
Arrays.stream(arr2)
.mapToObj(in -> in * 2)
.collect(Collectors.toCollection(() -> new ArrayList<>()));