前面我们说到collect
方法用于收集元素,并转换成我们需要的格式。而collect
方法的传参我们常用的不是自己实现Collector
接口,而是使用Collectors
类的方法,接下来就以例子说明一下Collectors
类的常用方法
1、toList
Collectors.toList
用于将流元素收集成一个List
集合,无需传参
1 2 3 4 5 6 7 8
| List<Integer> collect = Stream.of(1, 2, 3, 4, 5, 6) .filter(i->{ return i > 3; }) .collect(Collectors.toList()); System.out.println(collect);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @Data @AllArgsConstructor class User { private Integer id; private String userName; private Integer age;
}
public class Test { public static void main(String[] args) {
User user1 = new User(1, "张三", 18); User user2 = new User(2, "李四", 20); User user3 = new User(3, "王五", 22);
List<User> collect = Stream.of(user1, user2, user3) .filter(u->{ return u.getAge() > 19; }) .collect(Collectors.toList()); System.out.println(collect); } }
|
2、toSet
Collectors.toSet
用于将流元素收集成一个Set
集合,无需传参
1 2 3 4 5 6 7 8
| Set<Integer> collect = Stream.of(1, 2, 3, 4, 5, 6) .filter(i->{ return i > 3; }) .collect(Collectors.toSet()); System.out.println(collect);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @Data @AllArgsConstructor class User { private Integer id; private String userName; private Integer age;
}
public class Test { public static void main(String[] args) {
User user1 = new User(1, "张三", 18); User user2 = new User(2, "李四", 20); User user3 = new User(3, "王五", 22); User user4 = new User(3, "王五", 22);
Set<User> collect = Stream.of(user1, user2, user3, user4) .filter(u->{ return u.getAge() > 19; }) .collect(Collectors.toSet()); System.out.println(collect); } }
|
3、toMap
Collectors.toMap
可以将流元素返回成map
对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Data @AllArgsConstructor class User { private Integer id; private String userName; private Integer age;
}
public class Test { public static void main(String[] args) {
User user1 = new User(1, "张三", 18); User user2 = new User(2, "李四", 20); User user3 = new User(3, "王五", 22);
Map<Integer, String> collect = Stream.of(user1, user2, user3) .collect(Collectors.toMap(u -> u.getId(), u -> u.getUserName(), (oldValue, newValue) -> newValue)); System.out.println(collect); } }
|
Collectors.toMap
还有两个参数和四个参数的使用方法,两个参数只需要传key和value的生成函数,但是在有重复的key时会报异常。四个参数的,第四个参数是生成的map
类型,三个参数是默认的生成的是HashMap
类型的,上述也能改成
1 2 3
| Map<Integer, String> collect = Stream.of(user1, user2, user3) .collect(Collectors.toMap(u -> u.getId(), u -> u.getUserName(), (oldValue, newValue) -> newValue, LinkedHashMap::new)); System.out.println(collect);
|
使生成的map
类型是LinkedHashMap
4、joining
Collectors.joining
用于将流元素拼接成字符串返回,但是要求流元素要是字符格式,有三种传参方式,如下方拼接1, 2, 3, 4, 5, 6的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| String collect = Stream.of(1, 2, 3, 4, 5, 6) .map(i -> { return i.toString(); }) .collect(Collectors.joining()); System.out.println(collect);
String collect = Stream.of(1, 2, 3, 4, 5, 6) .map(i -> { return i.toString(); }) .collect(Collectors.joining("-")); System.out.println(collect);
String collect = Stream.of(1, 2, 3, 4, 5, 6) .map(i -> { return i.toString(); }) .collect(Collectors.joining("-" ,"前", "后")); System.out.println(collect);
|
5、mapping
Collectors.mapping
将流元素进行映射,需要传两个参数,一个是映射函数,一个是收集方法,效果和map
加collect
一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @Data @AllArgsConstructor class User { private Integer id; private String userName; private Integer age;
}
public class Test { public static void main(String[] args) {
User user1 = new User(1, "张三", 18); User user2 = new User(2, "李四", 20); User user3 = new User(3, "王五", 22);
List<String> collect = Stream.of(user1, user2, user3) .collect(Collectors.mapping( u -> u.getUserName(), Collectors.toList() )); System.out.println(collect); } }
|
基本等价于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Data @AllArgsConstructor class User { private Integer id; private String userName; private Integer age;
}
public class Test { public static void main(String[] args) {
User user1 = new User(1, "张三", 18); User user2 = new User(2, "李四", 20); User user3 = new User(3, "王五", 22);
List<String> collect = Stream.of(user1, user2, user3) .map(u -> u.getUserName()) .collect(Collectors.toList()); System.out.println(collect); } }
|
在后面的groupingBy
还会有其他例子
6、groupingBy
Collectors.groupingBy
用于给流元素进行分组,如下例子
先定义一个User
类和userList
的集合
1 2 3 4 5 6 7 8 9
| @Data @AllArgsConstructor public class User { private Integer id; private String userName; private Integer age; private String province; private Integer workDuration; }
|
1 2 3 4 5 6 7 8 9 10 11
| List<User> userList = new ArrayList<>(); userList.add(new User(1, "张三", 18, "广东省", 1800)); userList.add(new User(2, "李四", 19, "湖南省", 2500)); userList.add(new User(3, "王五", 20, "湖北省", 1526)); userList.add(new User(4, "赵六", 18, "湖北省", 2775)); userList.add(new User(5, "牛七", 25, "吉林省", 5778)); userList.add(new User(6, "张大炮", 24, "广东省", 2146)); userList.add(new User(7, "李小明", 21, "湖北省", 3789)); userList.add(new User(8, "赵有钱", 26, "四川省", 1458)); userList.add(new User(9, "王书", 26, "广东省", 1496)); userList.add(new User(10, "吴子明 ", 22, "吉林省", 4523));
|
6.1 例子1:根据省份进行分组
1 2 3
| Map<String, List<User>> collect = userList.stream() .collect(Collectors.groupingBy(User::getProvince)); System.out.println(collect);
|
结果为:
6.2 例子2、获取各个省份的用户数
1 2 3 4 5
| Map<String, Long> collect = userList.stream() .collect(Collectors.groupingBy(User::getProvince, Collectors.counting())); System.out.println(collect);
|
6.3 例子3、根据省份进行分组,但是value只需要userName
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Map<String, List<String>> collect = userList.stream() .collect(Collectors.groupingBy( User::getProvince, Collectors.mapping(User::getUserName, Collectors.toList()) )); System.out.println(collect);
Map<String, String> collect = userList.stream() .collect(Collectors.groupingBy( User::getProvince, Collectors.mapping(User::getUserName, Collectors.joining(",")) )); System.out.println(collect);
|
6.4 例子4、获取各个省份的工作时长之和
1 2 3 4 5 6 7 8
| Map<String, Integer> collect = userList.stream() .collect(Collectors.groupingBy( User::getProvince, Collectors.summingInt(user -> user.getWorkDuration())) ); System.out.println(collect);
|
7、collectingAndThen
Collectors.collectingAndThen
先对流进行一个收集,然后对收集的数据进行二次处理。该方法需要两个参数,第一个参数是收集的Collector
对象,第二个参数的二次处理的函数,并且第一个参数的返回对象是第二个参数的入参对象
7.1 例子1、将一串数字进行去重后转成List
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| List<Integer> collect = Stream.of(1, 2, 3, 4, 4, 5, 6, 2, 3, 5) .collect(Collectors.collectingAndThen( Collectors.toSet(), ArrayList::new )); System.out.println(collect);
List<Integer> collect = Stream.of(1, 2, 3, 4, 4, 5, 6, 2, 3, 5) .collect(Collectors.toSet()) .stream() .collect(Collectors.toList()); System.out.println(collect);
|
7.2 例子2、获取age最大的用户名
下面例子中的userList
是第6点groupingBy的userList
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| String collect = userList.stream() .collect(Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparing(User::getAge)), v -> v.get().getUserName() )); System.out.println(collect);
String collect = userList.stream() .collect(Collectors.maxBy(Comparator.comparing(User::getAge))) .get().getUserName(); System.out.println(collect);
|
7.3 例子3、根据用户的省份去重用户
下面例子中的userList
是第6点groupingBy的userList
1 2 3 4 5 6 7 8 9 10 11 12 13
| List<User> collect = userList.stream() .collect(Collectors.collectingAndThen( Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getProvince))), ArrayList::new )); System.out.println(collect);
List<User> collect = userList.stream() .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getProvince)))) .stream() .collect(Collectors.toList()); System.out.println(collect);
|
结果如下:
由上面的例子可以看出,collectingAndThen
是元素收集加额外处理两个步骤的合并