java l利用Collectors.groupingBy分组,并将每组的值转换为List<>
非常好的问题!以下是示例代码:
Map<String, List
这段代码将给定的字符串列表按照小写字母分组,并将每组的值转换为列表。你也可以根据需要更改分组依据和转换器。希望这个回答能够帮到你!
Collectors.groupingBy分组后统计list大小
使用 Java Collectors.groupingBy
分组并计算每组的列表大小
为了实现这一目标,可以利用 groupingBy
结合 counting()
方法。具体来说,在流操作中调用 .collect(Collectors.groupingBy(...))
来指定分组依据,并作为第二参数传入 Collectors.counting()
用于统计各分组内的元素数量。
下面是一个具体的例子,展示如何基于学生课程对学生进行分组,并统计每一门课的学生人数:
import java.util.*;
import java.util.stream.Collectors;
class Student {
private String name;
private String course;
public Student(String name, String course) {
this.name = name;
this.course = course;
}
public String getCourse() {
return course;
}
}
public class GroupAndCountExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Alice", "Math"),
new Student("Bob", "Physics"),
new Student("Charlie", "Math"),
new Student("David", "Chemistry")
);
Map<String, Long> groupCount = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.counting()));
System.out.println(groupCount);
}
}
上述代码会输出如下结果:
{Chemistry=1, Math=2, Physics=1}
此程序创建了一个包含不同学生的列表,这些学生注册了不同的课程。接着使用 stream().collect(Collectors.groupingBy())
将其按照所选课程分类,并通过 Collectors.counting()
统计每个类别下的学生数目[^2]。
对于更复杂的场景,比如需要进一步处理或转换数据,则可以在 groupingBy
中嵌套其他收集器来满足需求[^1]。
Collectors.groupingBy 分组之后排序
Java Stream Collectors GroupingBy 结果排序
当使用 Collectors.groupingBy
对数据进行分组后,可以通过多种方式对结果进行排序。一种常见的方式是在收集器链中加入额外的操作来实现这一点。
对于按照特定键值分组后的映射表(通常是 Map<K,V>
),如果希望按键排序,则可以在创建流之前先对源列表进行预处理;而如果是想要基于某些计算出来的汇总值排序,则可在最终收集阶段指定自定义比较逻辑。
按照键顺序排序的例子:
import java.util.*;
import java.util.stream.Collectors;
class Employee {
private String name;
private int salary;
private String department;
// Constructor, getters and setters...
}
public class Main {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("Alice", 70_000, "HR"),
new Employee("Bob", 80_000, "Engineering"),
new Employee("Charlie", 90_000, "Marketing")
);
TreeMap<String, Long> sortedGroupedByDepartment =
employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
() -> new TreeMap<>(),
Collectors.counting()));
System.out.println(sortedGroupedByDepartment);
}
}
这段代码展示了如何通过提供一个有序的集合工厂方法给定初始容量为零的新实例作为第二个参数传递给 groupingBy()
来获得自然排序的结果[^1]。
基于聚合函数返回值排序的方法:
另一种情况是当我们不仅关心分组依据本身还关注每组内部的数据特征时——比如总和、平均数等统计量。此时可以利用复合型收集器完成更复杂的任务,并且在最后一步应用 toMap()
或者其他形式的终端操作来自定义输出格式及其排列规则。
下面是一个例子说明怎样根据部门内员工薪资总额降序展示各个团队的信息:
employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment))
.entrySet().stream()
.sorted(Map.Entry.<String, List<Employee>>comparingByKey())
.map(entry -> entry.getKey() +
": Total Salary=" +
entry.getValue().stream()
.mapToInt(Employee::getSalary).sum())
.forEach(System.out::println);
这里先是进行了简单的分组,接着转换成条目集以便能够对其进行进一步加工,再调用 sorted()
方法并传入合适的比较器以决定元素间的相对位置关系,最后经过一系列中间运算得出所需信息并打印出来[^2]。
为了简化上述过程中的部分步骤以及提高可读性和灵活性,在实际开发过程中还可以考虑采用如下所示的一次性解决方案:
employees.stream()
.collect(Collectors.toMap(
Employee::getDepartment,
e -> Collections.singletonList(e),
(e1, e2) -> {
ArrayList<Employee> combined = new ArrayList<>(e1);
combined.addAll(e2);
return combined; },
LinkedHashMap::new)) // Keep insertion order or use another supplier like TreeMap for natural ordering.
.entrySet().stream()
.sorted((a,b)->Long.compare(b.getValue().stream().mapToInt(Employee::getSalary).sum(),
a.getValue().stream().mapToInt(Employee::getSalary).sum()))
.forEachOrdered(entry->System.out.printf("%s : %d\n",
entry.getKey(),
entry.getValue().stream().mapToInt(Employee::getSalary).sum()));
此片段实现了相同的功能但是更加紧凑直观一些[^3]。
相关推荐















