Java 8基本流到集合的映射方法

时间:2018-12-31 09:19:52

标签: java java-8 integer java-stream

这两种流创建方法之间在性能或最佳实践方面是否存在显着差异?

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))

6 个答案:

答案 0 :(得分:7)

是的,boxed()使用Integer.valueOf可以从cache检索一些Integer实例。

因此,您最好将版本与boxed()一起使用,或者使用Integer.valueOf而不是new Integer()。请注意,boxed()实际上是mapToObj(Integer::valueOf)的简写。

答案 1 :(得分:5)

第二个更好,因为在此示例中它不创建Integer个对象。

JLS 5.1.7

  

如果要装箱的值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)使用,因为此方法可能通过缓存经常请求的值而产生更好的时空性能

     

The Javadoc of Integer.valueOf(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::valueOfnew Integer()更有效率,因此我们应该选择boxed()


最佳做法:

除了性能上的差异外,boxed()使我们写的更少,并且更容易阅读。