Java 装箱流,用户希望利用基本类型流(primitive stream)创建集合,既可以使用 java.util.stream.IntStream
接口定义的 boxed
方法来包装元素,也可以使用合适的包装器类(wrapper class)来映射值,还可以使用 collect
方法的三参数形式。
Java 装箱流 问题描述
用户希望利用基本类型流(primitive stream)创建集合。
Java 装箱流 解决方案
既可以使用 java.util.stream.IntStream
接口定义的 boxed
方法来包装元素,也可以使用合适的包装器类(wrapper class)来映射值,还可以使用 collect
方法的三参数形式。
Java 装箱流 具体实例
在处理对象流(object stream)时,可以通过 Collectors
类提供的某种静态方法将流转换为集合。例如,对于一个给定的字符串流,例 3-8 显示了如何创建 List<String>
。
例 3-8 将字符串流转换为列表
List<String> strings = Stream.of("this", "is", "a", "list", "of", "strings")
.collect(Collectors.toList());
然而,同样的过程并不适合处理基本类型流,例 3-9 中的代码无法编译。
例 3-9 将
int
流转换为Integer
列表(无法编译)
IntStream.of(3, 1, 4, 1, 5, 9)
.collect(Collectors.toList()); // 无法编译
有三种替代方案可以解决这个问题。第一种方案是利用 boxed
方法,将 IntStream
转换为 Stream<Integer>
,如例 3-10 所示。
例 3-10 使用
boxed
方法
List<Integer> ints = IntStream.of(3, 1, 4, 1, 5, 9)
.boxed() ➊
.collect(Collectors.toList());
➊ 将 int
转换为 Integer
第二种方案是利用 mapToObj
方法,将基本类型流中的每个元素转换为包装类的一个实例,如例 3-11 所示。
例 3-11 使用
mapToObj
方法
List<Integer> ints = IntStream.of(3, 1, 4, 1, 5, 9)
.mapToObj(Integer::valueOf)
.collect(Collectors.toList())
mapToInt
、mapToLong
和 mapToDouble
方法将对象流解析为相关的基本类型流,与之类似,IntStream
、LongStream
与 DoubleStream
中的 mapToObj
方法将基本类型流转换为相关包装类的实例。在本例中,mapToObj
方法的参数为 Integer
类定义的静态方法 valueOf
。
出于性能方面的考虑,构造函数
Integer(int val)
已被 JDK 9 弃用,建议改用Integer.valueOf(int)
。
第三种方案是采用 collect
方法的三参数形式,其签名为:
<R> R collect(Supplier<R> supplier,
ObjIntConsumer<R> accumulator,
BiConsumer<R,R> combiner)
collect
方法的用法如例 3-12 所示。
例 3-12 使用
collect
方法的三参数形式
List<Integer> ints = IntStream.of(3, 1, 4, 1, 5, 9)
.collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll);
如例所示,Supplier
是 ArrayList<Integer>
的构造函数。累加器(accumulator)为 add
方法,表示如何为列表添加单个元素。仅在并行操作中使用的组合器(combiner)是 addAll
方法,它能将两个列表合二为一。尽管 collect
的三参数形式并不常见,但理解其用法对开发很有好处。
以上三种方案均无不妥,采用哪种方案取决于开发人员的编程风格。此外,如果希望将流转换为数组而非列表,那么采用 toArray
方法也不错,如例 3-13 所示。
例 3-13 将
IntStream
转换为intArray
int[] intArray = IntStream.of(3, 1, 4, 1, 5, 9).toArray();
本范例讨论的三种方案都是必不可少的,这是 Java 最初将基本数据类型与对象区别对待的结果,因泛型的引入而变得复杂。不过,一旦掌握要领,使用 boxed
或 mapToObj
方法还是很容易的。