所以我理解你可以有对象流,即Stream<T>
和专家原始流,例如IntStream
,DoubleStream
等。后者的一个好处是避免自动装箱。
另外,如果我们以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>
,那么肯定不需要包装/取消装箱,而IntConsumer
与Consumer<T>
相同吗?
答案 0 :(得分:5)
取消装箱在谓词内发生:在stream.filter(x -> x >= 50)
中,Predicate
基本上变为(Integer x) -> x.intValue() >= 50
,intValue()
是取消装箱的步骤。此外,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)
的快捷方式)。