Java 8原始流与集合映射方法

5
这两种流创建方法在性能或最佳实践方面有显著差异吗?
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社区的回答,我可以为新读者添加一些问题完整性的插件:

正如许多人指出的那样,.boxed() IntStream方法定义如下:

@Override
    public final Stream<Integer> boxed() {
        return mapToObj(Integer::valueOf);
    }

基本上重新定义问题,即以下哪个更好:

.mapToObj(in -> new Integer(in))

或者

.mapToObj(in -> Integer.valueOf(in))

4
.mapToObj((in) -> Integer.valueOf(in*2))翻译成中文:.mapToObj((in) -> Integer.valueOf(in*2)) 的意思是将流中的每个元素乘以2并转换为一个Integer对象。 - Hadi J
6
永远不要使用 new Integer,而是使用 Integer.valueOf。此外,请使用 Collectors.toList()。其他部分请编写基准测试。 - NoDataFound
3
除此之外,自Java 9开始,“new Integer(int x)”也被标记为“@Deprecated”,因此最好避免使用它。 - Naman
6个回答

7

是的,boxed()使用了Integer.valueOf,这可以从缓存中检索出一些Integer实例。

因此,您应该使用带有boxed()的版本(最好),或者使用Integer.valueOf而不是new Integer()。请注意,boxed()实际上是mapToObj(Integer::valueOf)的简写形式。


1
Tomasz,我选择你的答案作为被接受的答案,因为:它是最受欢迎的,相对于其他提供反馈的用户,你的声誉相对较小,并且涵盖了所有方面。而且我们都是波兰人;)开个玩笑! - Tomas
@Tomas “我选择你的答案作为被接受的答案,因为……” 那么也许你应该接受答案来表示如此;-) - Ousmane D.
@Aomine 哎呀,我的错 :) - Tomas

5
第二种方法更好,因为在这个例子中它不会创建任何Integer对象。
来自JLS 5.1.7 如果被装箱的值p是一个介于-128和127(包括边界)之间的int类型,则让r1和r2成为p的任意两个装箱转换的结果。始终有r1 == r2。
一般来说,您不应调用包装类型的new方法,而应使用它们的static工厂方法 - 例如Integer.valueOf

4
从最佳实践的角度来看,第二种方法更可取,因为当你想要将原始值装箱时,boxed就是专门为此目的创建的,并以最优化的方式完成,而mapToObj虽然也可以用来实现相同的功能,但不是惯用的方法。
此外,建议不再使用原始包装类型构造器,而是更喜欢使用valueOf方法。这是因为这些构造器已经被弃用,而且通过使用valueOf,与构造器相比,它减少了内存占用,从而提高了性能。

4

3
第二种方法会有效地使用JVM的整数缓存,因此在性能上更好,并且是最佳实践(不要实例化装箱类型,而是让虚拟机为您完成)。如果您将new Integer(in)更改为Integer.valueOf(in),则可以模仿相同的行为。

1

为了性能和最佳实践,我们应该选择使用boxed()而不是mapToObj((in) -> new Integer(in))


性能:

请看下面的boxed()源代码(在抽象类IntPipeline<E_IN>中实现了IntStream,位于java.util.stream包中):

@Override
    public final Stream<Integer> boxed() {
        return mapToObj(Integer::valueOf);
    }

所以它正在使用 Integer::valueOf 调用 mapToObj()。请注意,通过重复使用缓存的值,Integer::valueOfnew Integer() 更有效率,因此我们应该选择 boxed()

最佳实践:

除了性能差异外,使用 boxed() 可以减少代码量,并且更易于阅读。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接