原始流与对象流和发生的实际装箱

时间:2016-02-04 18:49:30

标签: java java-stream primitive autoboxing

所以我理解你可以有对象流,即Stream<T>和专家原始流,例如IntStreamDoubleStream等。后者的一个好处是避免自动装箱。

另外,如果我们以IntStream为例,它会有专门的操作,例如接受IntPredicate的过滤器。

我想知道我是否有一个IntStream vs Stream<Integer>,此时你可以节省拳击,例如

intstream.filter(x -> x >= 50).forEach(x -> System.out.println(x));

VS

stream.filter(x -> x >= 50).forEach(x -> System.out.println(x));

在第一个例子中,我没有看到拳击或拆箱。在第二个例子中,拳击/拆箱发生在哪里?因为如果流是Stream<Integer>且过滤器接受Predicate<Integer>,那么肯定不需要包装/取消装箱,而IntConsumerConsumer<T>相同吗?

2 个答案:

答案 0 :(得分:5)

取消装箱在谓词内发生:在stream.filter(x -> x >= 50)中,Predicate基本上变为(Integer x) -> x.intValue() >= 50intValue()是取消装箱的步骤。此外,System.out.println在最终被调用的Integer.toString的实现中自行进行了一些拆箱。

答案 1 :(得分:2)

使用Stream<Integer>您的信息流已经装箱。因此,根据您创建它的方式,有几种可能性:

  • 您最初已装箱值。例如,您输入List<Integer> list并写道:

    stream = list.stream();
    
  • 您在创建流时将您的值装箱。例如,您创建了它:

    stream = Stream.iterate(1, x -> x+1);
    

    在这种情况下,第一个参数被装箱为Integer.valueOf(1),并且每个lambda(即UnaryOperator<Integer>)调用也会发生取消装箱/装箱。你有效地做到了:

    stream = Stream.iterate(Integer.valueOf(1), x -> Integer.valueOf(x.intValue()+1));
    
  • 您通过上游中间操作明确地装箱了您的来源。例如:

    stream = IntStream.range(0, 1000).boxed();
    

    在这种情况下,装箱是在.boxed()操作中执行的(这是.mapToObj(Integer::valueOf)的快捷方式)。