Skip to content
  • Collectors.groupingBy 有三种主要的重载形式,下面通过代码示例来详细说明它们的使用。

    1. 基本形式:

    按某个函数进行分组

    java
    List<String> list = Arrays.asList("apple", "banana", "cherry", "apricot");
    
    Map<Character, List<String>> grouped = list.stream()
        .collect(Collectors.groupingBy(s -> s.charAt(0)));
    
    System.out.println(grouped);

    输出:

    text
    {a=[apple, apricot], b=[banana], c=[cherry]}

    说明:

    • 功能:按照字符串的首字母将字符串分组。
    • 返回类型Map<Character, List<String>>,键是字符串的首字母,值是具有相同首字母的字符串集合。

    2. 带下游收集器:

    除了分组外,还可以对每个组内的元素进行进一步处理,比如计数、求和等。

    java
    List<String> list = Arrays.asList("apple", "banana", "apple", "cherry", "banana");
    
    Map<String, Long> counts = list.stream()
        .collect(Collectors.groupingBy(
            Function.identity(), // 按照字符串分组
            Collectors.counting() // 计算每组的元素个数
        ));
    
    System.out.println(counts);

    输出:

    text
    {apple=2, banana=2, cherry=1}

    说明:

    • 功能:按字符串进行分组,并计算每个组中字符串的个数。
    • 返回类型Map<String, Long>,键是字符串,值是该字符串在列表中出现的次数。

    3. 带自定义 Map 和下游收集器:

    除了分组和下游收集器之外,你还可以指定一个自定义的 Map 实现类。

    List<String> list = Arrays.asList("apple", "banana", "cherry", "apricot");
    
    Map<Character, Set<String>> groupedSet = list.stream()
        .collect(Collectors.groupingBy(
            s -> s.charAt(0), // 按首字母分组
            TreeMap::new, // 使用 TreeMap 作为 Map 实现
            Collectors.toSet() // 组内元素使用 Set 存储
        ));
    
    System.out.println(groupedSet);

    输出:

    text
    {a=[apple, apricot], b=[banana], c=[cherry]}

    说明:

    • 功能:按首字母分组,并将每个组内的元素存储在 Set 中,最终使用 TreeMap 来存储分组的结果(TreeMap 保证按字母顺序排序)。
    • 返回类型Map<Character, Set<String>>,其中键是字符,值是一个去重的字符串集合。

    总结

    • 第一种形式:只进行分组,返回 Map<K, List<T>>
    • 第二种形式:除了分组,还可以使用下游收集器(如 counting()summarizingInt() 等),返回 Map<K, D>
    • 第三种形式:自定义 Map 类型,同时还可以指定下游收集器,返回 Map<K, D>