# collectors

back

Stream中有两个个方法collectcollectingAndThen用于对流中的数据进行处理,可以对流中的数据进行聚合操作

  • 将流中的数据转成集合类型: toList、toSet、toMap、toCollection
  • 将流中的数据(字符串)使用分隔符拼接在一起:joining
  • 对流中的数据求最大值maxBy最小值minBy求和summingInt求平均值averagingDouble
  • 对流中的数据进行映射处理 mapping
  • 对流中的数据分组:groupingBy、partitioningBy
  • 对流中的数据累计计算:reducing

# 示例

# 累计操作

back

@Test
public void testReducing(){

    // sum: 是每次累计计算的结果,b是Function的结果
    System.out.println(Stream.of(1, 3, 4).collect(Collectors.reducing(0, x -> x + 1, (sum, b) -> {
        System.out.println(sum + "-" + b);
        return sum + b;
    })));


     // 下面代码是对reducing函数功能实现的描述,用于理解reducing的功能
    int sum = 0;
    List<Integer> list3 = Arrays.asList(1, 3, 4);
    for (Integer item : list3) {
        int b = item + 1;
        System.out.println(sum + "-" + b);
        sum = sum + b;
    }
    System.out.println(sum);


    // 注意reducing可以用于更复杂的累计计算,加减乘除或者更复杂的操作
    // result = 2 * 4 * 5 = 40
    System.out.println(Stream.of(1, 3, 4).collect(Collectors.reducing(1, x -> x + 1, (result, b) -> {
        System.out.println(result + "-" + b);
        return result * b;
    })));
}
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
28

# 分组

back

public class User {
    private Long id;
    private String username;
    private Integer type;

    // Getter & Setter & toString
}

@Test
public void testGroupBy(){
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    // 奇偶数分组:奇数分一组,偶数分一组
    // groupingBy(Function<? super T, ? extends K> classifier) 参数是Function类型,Function返回值可以是要分组的条件,也可以是要分组的字段
    // 返回的结果是Map,其中key的数据类型为Function体中计算类型,value是List<T>类型,为分组的结果
    Map<Boolean, List<Integer>> result = list.stream().collect(Collectors.groupingBy(item -> item % 2 == 0));
    // {false=[1, 3, 5, 7, 9], true=[2, 4, 6, 8, 10]}
    System.out.println(result);


     // partitioningBy 用于分成两组的情况
    Map<Boolean, List<Integer>> twoPartiton = list.stream().collect(Collectors.partitioningBy(item -> item % 2 == 0));
    System.out.println(twoPartiton);


    User user = new User(1L, "zhangsan", 1);
    User user2 = new User(2L, "lisi", 2);
    User user3 = new User(3L, "wangwu", 3);
    User user4 = new User(4L, "fengliu", 1);
    List<User> users = Arrays.asList(user, user2, user3, user4);
    // 根据某个字段进行分组
    Map<Integer, List<User>> userGroup = users.stream().collect(Collectors.groupingBy(item -> item.type));

    /**
     * key 为要分组的字段
     * value 分组的结果
     * {
     *  1=[User{id=1, username='zhangsan', type=1}, User{id=4, username='fengliu', type=1}],
     *  2=[User{id=2, username='lisi', type=2}],
     *  3=[User{id=3, username='wangwu', type=3}]
     * }
     */
    System.out.println(userGroup);
}

// 分组并对分组中的数据统计
@Test
public void testGroupBy2() {
    Foo foo1 = new Foo(1, 2);
    Foo foo2 = new Foo(2, 23);
    Foo foo3 = new Foo(2, 6);
    List<Foo> list = new ArrayList<>(4);
    list.add(foo1);
    list.add(foo2);
    list.add(foo3);
    Map<Integer, IntSummaryStatistics> collect = list.stream().collect(Collectors.groupingBy(Foo::getCode, Collectors.summarizingInt(Foo::getCount)));
    IntSummaryStatistics statistics1 = collect.get(1);
    IntSummaryStatistics statistics2 = collect.get(2);
    System.out.println(statistics1.getSum());
    System.out.println(statistics1.getAverage());
    System.out.println(statistics1.getMax());
    System.out.println(statistics1.getMin());
    System.out.println(statistics1.getCount());

    System.out.println(statistics2.getSum());
    System.out.println(statistics2.getAverage());
    System.out.println(statistics2.getMax());
    System.out.println(statistics2.getMin());
    System.out.println(statistics2.getCount());
}
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 流转集合

back

@Test
public void testToCollection(){
    List<Integer> list = Arrays.asList(1, 2, 3);

    // [10, 20, 30]
    List<Integer> collect = list.stream().map(i -> i * 10).collect(Collectors.toList());

    // [20, 10, 30]
    Set<Integer> collect1 = list.stream().map(i -> i * 10).collect(Collectors.toSet());

    // {key1=value:10, key2=value:20, key3=value:30}
    Map<String, String> collect2 = list.stream().map(i -> i * 10).collect(Collectors.toMap(key -> "key" + key/10, value -> "value:" + value));

    // [1, 3, 4]
    TreeSet<Integer> collect3= Stream.of(1, 3, 4).collect(Collectors.toCollection(TreeSet::new));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@ToString
@AllArgsConstructor
@RequiredArgsConstructor
public class User {
    private Long id;
    private String username;
}

@Test
public void testToMap() {
    List<User> userList = Arrays.asList(
         new User(1L, "mengday"),
         new User(2L, "mengdee"),
         new User(3L, "mengdy")
    );

    // toMap 可用于将List转为Map,便于通过key快速查找到某个value
    Map<Long, User> userIdAndModelMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
    User user = userIdAndModelMap.get(1L);
    // User(id=1, username=mengday)
    System.out.println(user);

    Map<Long, String> userIdAndUsernameMap = userList.stream().collect(Collectors.toMap(User::getId, User::getUsername));
    String username = userIdAndUsernameMap.get(1L);
    // mengday
    System.out.println(username);
}
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
28

# 集合元素拼接

back

@Test
public void testJoining(){
    // a,b,c
    List<String> list2 = Arrays.asList("a", "b", "c");
    String result = list2.stream().collect(Collectors.joining(","));

    // Collectors.joining(",")的结果是:a,b,c  然后再将结果 x + "d"操作, 最终返回a,b,cd
    String str= Stream.of("a", "b", "c").collect(Collectors.collectingAndThen(Collectors.joining(","), x -> x + "d"));
}
1
2
3
4
5
6
7
8
9

# 元素聚合

back

@Test
public void test(){
    // 求最值 3
    List<Integer> list = Arrays.asList(1, 2, 3);
    Integer maxValue = list.stream().collect(Collectors.collectingAndThen(Collectors.maxBy((a, b) -> a - b), Optional::get));

    // 最小值 1
    Integer minValue = list.stream().collect(Collectors.collectingAndThen(Collectors.minBy((a, b) -> a - b), Optional::get));

    // 求和 6
    Integer sumValue = list.stream().collect(Collectors.summingInt(item -> item));

    // 平均值 2.0
    Double avg = list.stream().collect(Collectors.averagingDouble(x -> x));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void test(){
    // 映射:先对集合中的元素进行映射,然后再对映射的结果使用Collectors操作
    // A,B,C
    Stream.of("a", "b", "c").collect(Collectors.mapping(x -> x.toUpperCase(), Collectors.joining(",")));
}
1
2
3
4
5
6