我觉得Java 8 Streams中的map()
和mapToObj()
方法之间没有区别。在两者中我们都可以创建对象并将对象返回到流中,因此为什么这些方法存在为两个,而不仅仅是一个。
你能用例子给我解释吗?
答案 0 :(得分:32)
你会看到这种酷炫的模式。 Stream
类包括IntStream
,LongStream
,DoubleStream
等。这样您就可以在流操作中使用基本类型。因为否则您必须使用Stream<Integer>
或Stream<Double>
,这将设置值。
同样,map
方法也可以这样做。在Stream<T>
课程中,有mapToInt
,mapToDouble
方法,但IntStream
,DoubleStream
类的情况略有不同。
在IntStream
中,map
方法采用IntUnaryOperator
,将int映射到int。如果要将流映射到Stream<T>
,则必须使用mapToObj
。 mapToObj
是一个好名字,因为它区别于映射到整数的map
。它表示流从IntStream
更改为Stream<T>
。 mapToObj
被命名的原因与mapToInt
被命名的原因相同 - 表示Stream
类型/
答案 1 :(得分:12)
数据类型的primitive
和object
版本(即int和Integer,double和Double等)在Java中并不真正相互兼容。通过auto-boxing/unboxing
的额外步骤使它们兼容。因此,如果您有一个原始整数流并且如果您尝试使用Stream和Function的对象版本(即流和函数,则会产生装箱和拆箱的成本。
要消除此问题,功能包包含primitive specialized versions of streams
以及functional interfaces
。例如,您应该使用Stream<Integer>
而不是IntStream
。您现在可以使用IntFunction处理流的每个元素。这样可以完全避免自动装箱/拆箱。
因此,每当您想要处理原始元素流时,您应该使用原始专用流(即IntStream,LongStream和DoubleStream)和原始专用功能接口(即IntFunction,IntConsumer,IntSupplier等)来实现更好的性能
还有一点需要注意的是,没有任何原始的专用功能接口(如IntFunction,DoubleFunction或IntConsumer)扩展非原始功能接口(即Function,Consumer等)。
java.util.function package
包含所有功能接口的int,double和long(但没有浮点)版本。例如,有一个IntFunction,一个DoubleFunction和一个LongFunction,它们是Function的int,double和long版本。这些函数与流的原始专用版本一起使用,例如IntStream,DoubleStream和LongStream。
我们举一些例子:
Stream stream = Stream.of(1, 2, 3); //Will compile fine
IntStream intStream = IntStream.of(4, 5, 6); //Will compile fine
Stream s = IntStream.of(4, 5, 6); //Does not compile
Stream s = IntStream.of(4, 5, 6).mapToObj(e -> e); //mapToObj method is needed
IntStream is = Stream.of(4, 5, 6).mapToInt(e -> e); //mapToInt method is needed
总之,您使用mapToObj
的原因与您使用mapToInt
的原因相同,即更改流类型。