本文目录导读:

我来给你展示 groupingBy 的多个实用案例,从基础到高级:
基础分组
import java.util.*;
import java.util.stream.Collectors;
public class GroupingByDemo {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("张三", 25, "北京"),
new Person("李四", 30, "上海"),
new Person("王五", 25, "北京"),
new Person("赵六", 35, "广州"),
new Person("孙七", 30, "深圳"),
new Person("周八", 25, "上海")
);
// 1. 按城市分组
Map<String, List<Person>> byCity = people.stream()
.collect(Collectors.groupingBy(Person::getCity));
System.out.println("按城市分组: " + byCity);
// 2. 按年龄分组
Map<Integer, List<Person>> byAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
System.out.println("按年龄分组: " + byAge);
}
}
class Person {
private String name;
private int age;
private String city;
public Person(String name, int age, String city) {
this.name = name;
this.age = age;
this.city = city;
}
// getter/setter
public String getName() { return name; }
public int getAge() { return age; }
public String getCity() { return city; }
@Override
public String toString() {
return name + "(" + age + "岁)";
}
}
分组后计数
public class GroupingCountDemo {
public static void main(String[] args) {
List<String> words = Arrays.asList(
"apple", "banana", "apple", "orange",
"banana", "grape", "apple"
);
// 统计每个单词出现次数
Map<String, Long> wordCount = words.stream()
.collect(Collectors.groupingBy(
word -> word,
Collectors.counting()
));
System.out.println("单词计数: " + wordCount);
// 按字符串长度分组并计数
Map<Integer, Long> lengthCount = words.stream()
.collect(Collectors.groupingBy(
String::length,
Collectors.counting()
));
System.out.println("按长度计数: " + lengthCount);
}
}
分组后聚合操作
public class GroupingAggregationDemo {
public static void main(String[] args) {
List<Order> orders = Arrays.asList(
new Order("A001", "电子产品", 1000.0),
new Order("A002", "服装", 200.0),
new Order("A003", "电子产品", 1500.0),
new Order("A004", "食品", 100.0),
new Order("A005", "服装", 350.0),
new Order("A006", "电子产品", 800.0)
);
// 1. 按类别求销售额总和
Map<String, Double> totalByCategory = orders.stream()
.collect(Collectors.groupingBy(
Order::getCategory,
Collectors.summingDouble(Order::getAmount)
));
System.out.println("各类别销售额: " + totalByCategory);
// 2. 按类别求平均销售额
Map<String, Double> avgByCategory = orders.stream()
.collect(Collectors.groupingBy(
Order::getCategory,
Collectors.averagingDouble(Order::getAmount)
));
System.out.println("各类别平均销售额: " + avgByCategory);
// 3. 按类别求最高销售额
Map<String, Optional<Order>> maxByCategory = orders.stream()
.collect(Collectors.groupingBy(
Order::getCategory,
Collectors.maxBy(Comparator.comparingDouble(Order::getAmount))
));
System.out.println("各类别最高订单: " + maxByCategory);
// 4. 按类别汇总统计信息
Map<String, DoubleSummaryStatistics> statsByCategory = orders.stream()
.collect(Collectors.groupingBy(
Order::getCategory,
Collectors.summarizingDouble(Order::getAmount)
));
System.out.println("电子产品统计: " + statsByCategory.get("电子产品"));
}
}
class Order {
private String id;
private String category;
private double amount;
public Order(String id, String category, double amount) {
this.id = id;
this.category = category;
this.amount = amount;
}
public String getCategory() { return category; }
public double getAmount() { return amount; }
@Override
public String toString() {
return id + "(" + category + "): " + amount;
}
}
多级分组
public class MultiGroupingDemo {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("张三", "技术部", "北京", 25),
new Employee("李四", "市场部", "上海", 30),
new Employee("王五", "技术部", "北京", 28),
new Employee("赵六", "财务部", "广州", 35),
new Employee("孙七", "市场部", "北京", 27),
new Employee("周八", "技术部", "上海", 32)
);
// 多级分组:先按部门,再按城市
Map<String, Map<String, List<Employee>>> byDeptAndCity = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.groupingBy(Employee::getCity)
));
System.out.println("多级分组结果: ");
byDeptAndCity.forEach((dept, cityMap) -> {
System.out.println(" " + dept + ": " + cityMap);
});
// 多级分组:先按城市,再按年龄段
Map<String, Map<String, List<Employee>>> byCityAndAgeGroup = employees.stream()
.collect(Collectors.groupingBy(
Employee::getCity,
Collectors.groupingBy(emp -> {
if (emp.getAge() < 30) return "30岁以下";
else return "30岁及以上";
})
));
System.out.println("\n按城市和年龄段分组: ");
byCityAndAgeGroup.forEach((city, ageMap) -> {
System.out.println(" " + city + ": " + ageMap);
});
}
}
class Employee {
private String name;
private String department;
private String city;
private int age;
public Employee(String name, String department, String city, int age) {
this.name = name;
this.department = department;
this.city = city;
this.age = age;
}
public String getDepartment() { return department; }
public String getCity() { return city; }
public int getAge() { return age; }
@Override
public String toString() {
return name + "(" + age + "岁)";
}
}
分组后转换为其他集合类型
public class GroupingCollectDemo {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("001", "张三", 85, "一班"),
new Student("002", "李四", 92, "二班"),
new Student("003", "王五", 78, "一班"),
new Student("004", "赵六", 88, "二班"),
new Student("005", "孙七", 95, "一班")
);
// 1. 分组后只收集姓名到Set
Map<String, Set<String>> namesByClass = students.stream()
.collect(Collectors.groupingBy(
Student::getClassName,
Collectors.mapping(Student::getName, Collectors.toSet())
));
System.out.println("按班级收集姓名: " + namesByClass);
// 2. 分组后收集为特定Map类型
Map<String, List<Student>> treeMapResult = students.stream()
.collect(Collectors.groupingBy(
Student::getClassName,
TreeMap::new, // 指定Map类型
Collectors.toList()
));
System.out.println("TreeMap结果: " + treeMapResult);
// 3. 分组后拼接姓名
Map<String, String> joinedNames = students.stream()
.collect(Collectors.groupingBy(
Student::getClassName,
Collectors.mapping(Student::getName,
Collectors.joining(", ", "[", "]"))
));
System.out.println("拼接姓名: " + joinedNames);
}
}
class Student {
private String id;
private String name;
private int score;
private String className;
public Student(String id, String name, int score, String className) {
this.id = id;
this.name = name;
this.score = score;
this.className = className;
}
public String getName() { return name; }
public String getClassName() { return className; }
@Override
public String toString() {
return name + "(成绩:" + score + ")";
}
}
分组后排序和限制
public class GroupingSortLimitDemo {
public static void main(String[] args) {
List<Product> products = Arrays.asList(
new Product("手机", "电子", 5000),
new Product("电脑", "电子", 8000),
new Product("耳机", "电子", 500),
new Product("T恤", "服装", 100),
new Product("牛仔裤", "服装", 300),
new Product("面包", "食品", 15),
new Product("牛奶", "食品", 10)
);
// 每个类别中价格最高的商品
Map<String, Optional<Product>> topByCategory = products.stream()
.collect(Collectors.groupingBy(
Product::getCategory,
Collectors.maxBy(Comparator.comparingInt(Product::getPrice))
));
System.out.println("各类别最贵商品: ");
topByCategory.forEach((cat, prod) ->
System.out.println(" " + cat + ": " + prod.orElse(null)));
// 每个类别的商品数量,按数量排序
Map<String, Long> countByCategory = products.stream()
.collect(Collectors.groupingBy(
Product::getCategory,
Collectors.counting()
));
// 排序输出
countByCategory.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.forEach(entry ->
System.out.println(entry.getKey() + ": " + entry.getValue() + "件"));
}
}
class Product {
private String name;
private String category;
private int price;
public Product(String name, String category, int price) {
this.name = name;
this.category = category;
this.price = price;
}
public String getCategory() { return category; }
public int getPrice() { return price; }
@Override
public String toString() {
return name + "(" + price + "元)";
}
}
实际业务场景示例
public class BusinessScenarioDemo {
public static void main(String[] args) {
// 模拟电商订单数据
List<Order> orders = generateOrders();
// 场景1:统计每个地区的订单数量和总金额
Map<String, Map<String, Object>> regionStats = orders.stream()
.collect(Collectors.groupingBy(
Order::getRegion,
Collectors.collectingAndThen(
Collectors.toList(),
list -> {
Map<String, Object> stats = new HashMap<>();
stats.put("订单数", list.size());
stats.put("总金额", list.stream()
.mapToDouble(Order::getAmount)
.sum());
stats.put("客户数", list.stream()
.map(Order::getCustomerId)
.distinct()
.count());
return stats;
}
)
));
System.out.println("各地区统计: ");
regionStats.forEach((region, stats) ->
System.out.println(" " + region + ": " + stats));
// 场景2:找出每个客户购买最多的商品类别
Map<String, Optional<String>> favoriteCategory = orders.stream()
.collect(Collectors.groupingBy(
Order::getCustomerId,
Collectors.groupingBy(Order::getCategory, Collectors.counting())
))
.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
));
System.out.println("\n客户偏好: ");
favoriteCategory.forEach((customer, cat) ->
System.out.println(" " + customer + ": " + cat.orElse("无")));
}
private static List<Order> generateOrders() {
List<Order> orders = new ArrayList<>();
Random random = new Random();
String[] regions = {"北京", "上海", "广州", "深圳"};
String[] categories = {"电子产品", "服装", "食品", "家居"};
String[] customers = {"C001", "C002", "C003", "C004"};
for (int i = 0; i < 100; i++) {
orders.add(new Order(
"O" + System.currentTimeMillis() + i,
customers[random.nextInt(customers.length)],
categories[random.nextInt(categories.length)],
regions[random.nextInt(regions.length)],
10 + random.nextInt(990)
));
}
return orders;
}
}
class Order {
private String orderId;
private String customerId;
private String category;
private String region;
private double amount;
public Order(String orderId, String customerId, String category,
String region, double amount) {
this.orderId = orderId;
this.customerId = customerId;
this.category = category;
this.region = region;
this.amount = amount;
}
public String getCustomerId() { return customerId; }
public String getCategory() { return category; }
public String getRegion() { return region; }
public double getAmount() { return amount; }
}
- 基础分组:
groupingBy(Function)按单个字段分组 - 分组计数:配合
counting()统计数量 - 分组合计:配合
summingInt/Double计算总和 - 多级分组:嵌套
groupingBy实现多维度分组 - 分组转换:使用
mapping转换元素类型 - 指定Map类型:使用
TreeMap等保证顺序 - 聚合操作:
maxBy,minBy,averagingInt等
这些示例涵盖了日常开发中95%以上的 groupingBy 使用场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播