这两种流创建方法之间在性能或最佳实践方面是否存在显着差异?
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<>()));
感谢堆栈社区的答案,我可以为新读者添加一些附加内容,以质疑其完整性:
许多人指出,.boxed()
IntStream方法定义为:
@Override
public final Stream<Integer> boxed() {
return mapToObj(Integer::valueOf);
}
基本上重新定义了以下哪个更好的问题:
.mapToObj(in -> new Integer(in))
或
.mapToObj(in -> Integer.valueOf(in))
答案 0 :(得分:7)
是的,boxed()
使用Integer.valueOf
可以从cache检索一些Integer
实例。
因此,您最好将版本与boxed()
一起使用,或者使用Integer.valueOf
而不是new Integer()
。请注意,boxed()
实际上是mapToObj(Integer::valueOf)
的简写。
答案 1 :(得分:5)
第二个更好,因为在此示例中它不创建Integer
个对象。
如果要装箱的值p是... -128至127(含)之间的int ...,则令r1和r2是p的两次装箱转换的结果。 r1 == r2总是这样。
通常来说,您不应在包装类型上调用new
,而应使用其static
工厂方法-例如Integer.valueOf
答案 2 :(得分:4)
从最佳实践的角度来看,第二种方法是更可取的,因为当您想装箱原始值boxed
正是为此目的而创建,并且以尽可能最佳的方式这样做时,而mapToObj
,尽管可以用来实现相同的目的,但这不是惯用的方法。
此外,建议不要再使用原始包装器类型构造函数,而建议使用valueOf
方法,这是因为这些构造函数已被弃用,并且通过使用valueOf
与构造函数相比,减少了内存占用,从而提高了性能。
答案 3 :(得分:3)
第二个将有效地使用jvm的整数缓存,因此在性能和最佳实践方面都将更好(不要实例化盒装类型,而应让vm为您完成)。
如果您将new Integer(in)
更改为Integer.valueOf(in)
,则可以模仿相同的行为
答案 4 :(得分:3)
IntStream.boxed()
使用Integer.valueOf(int)
,它是Integer(int)
的优化版本*。
在内部,boxed()
被定义为mapToObj(Integer::valueOf)
。
*此方法通常应优先于构造方法
Integer(int)
使用,因为此方法可能通过缓存经常请求的值而产生更好的时空性能。
答案 5 :(得分:1)
关于性能和最佳做法,我们应该选择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()
使我们写的更少,并且更容易阅读。