您的位置:

Java Stream Collect详解

一、Collect的简介

Collect是Java 8 Stream API中一种非常实用的终止操作,可以将Stream中的数据转化为特定的容器(Collection)或 Map对象,而且可以自定义转化的方式。这样可以方便地将Stream中的数据转换成我们需要的格式。

Collect方法的具体实现位于Collectors类中,它包含了很多静态方法来实现收集器,包括toList、toSet、toMap等等。这些方法都返回一个Collector接口,用于对Stream中的数据进行转化。

二、toList和toSet

toList和toSet方法是比较常用的Collector接口方法,对于我们需要将Stream数据转换为List或Set类型时,非常方便。

1. toList方法

toList方法将Stream中的数据转化为List类型,常用于将Stream流中的数据转化为List类型的集合,如下代码所示:


List<String> list = Stream.of("Java", "Python", "Go")
                           .filter(s -> s.length() > 2) // 过滤出长度大于2的字符串
                           .map(String::toUpperCase) // 将字符串转换为大写
                           .collect(Collectors.toList()); // 转换为List类型

执行结果:[JAVA, PYTHON]

2. toSet方法

toSet方法将Stream中的数据转化为Set类型,常用于将Stream流中的数据转化为Set类型的集合,如下代码所示:


Set<String> set = Stream.of("Java", "Python", "Go")
                          .filter(s -> s.length() > 2) // 过滤出长度大于2的字符串
                          .map(String::toUpperCase) // 将字符串转换为大写
                          .collect(Collectors.toSet()); // 转换为Set类型

执行结果:[PYTHON, JAVA]

三、toMap方法

toMap方法可以将Stream中的数据转化为Map类型,常用于将Stream流中的数据转化为Map类型的集合。需要注意的是,如果Stream中存在相同的key,就会抛出IllegalStateException异常。

1. 简单的toMap使用方法

toMap方法可以使用Function类型的键提取器和映射器,来将Stream流中的数据转化为Map类型的集合,如下代码所示:


Map<String, Integer> map = Stream.of("a", "bb", "ccc")
                                       .collect(Collectors.toMap(String::toUpperCase, String::length));

执行结果:{CCC=3, BB=2, A=1}

2. toMap方法指定重复键值的处理方式

toMap方法默认情况下,如果Stream流中存在相同的key,就会抛出IllegalStateException异常。但是我们可以通过指定后一个值覆盖前一个值的方式来解决这个问题。请看下面的代码:


Map<String, Integer> map = Stream.of("a", "bb", "cc", "dd")
                                       .collect(Collectors.toMap(String::length, String::length, (a, b) -> b));

执行结果:{1=1, 2=2}

四、joining方法

joining方法用于将字符序列(CharSequence)中的元素连接成一个字符串。默认情况下,joining方法会将字符串连接为逗号分隔的形式,如下代码所示:


String str = Stream.of("Java", "Python", "Go").collect(Collectors.joining());

执行结果:JavaPythonGo

joining方法也可以接受一个字符串作为分隔符,如下代码所示:


String str = Stream.of("Java", "Python", "Go").collect(Collectors.joining("-"));

执行结果:Java-Python-Go

五、summing方法

summing方法用于将Stream流中数字类型的元素进行求和。下面是一个使用summing方法的例子:


int sum = Stream.of(1, 2, 3, 4, 5).collect(Collectors.summingInt(Integer::intValue));

执行结果:15

六、groupingBy方法

groupingBy方法用于根据某个条件进行分组。下面是一个使用groupingBy方法的例子:


Map<Integer, List<String>> map = Stream.of("Java", "Python", "Go", "C", "C++")
                                           .collect(Collectors.groupingBy(String::length));

执行结果:{1=[C], 2=[Go, C++], 4=[Java], 6=[Python]}

七、partitioningBy方法

partitioningBy方法用于将Stream流中的元素按照一个条件分为两部分,返回结果是一个Map类型,其中的key值是true或false,分别代表满足条件和不满足条件的元素集合。下面是一个使用partitioningBy方法的例子:


Map<Boolean, List<String>> map = Stream.of("Java", "Python", "C", "Go", "C++")
                                         .collect(Collectors.partitioningBy(s -> s.startsWith("J")));

执行结果:{false=[Python, C, Go, C++], true=[Java]}