groupingBy案例

wen java案例 1

本文目录导读:

groupingBy案例

  1. 基础分组
  2. 分组后计数
  3. 分组后聚合操作
  4. 多级分组
  5. 分组后转换为其他集合类型
  6. 分组后排序和限制
  7. 实际业务场景示例

我来给你展示 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; }
}
  1. 基础分组groupingBy(Function) 按单个字段分组
  2. 分组计数:配合 counting() 统计数量
  3. 分组合计:配合 summingInt/Double 计算总和
  4. 多级分组:嵌套 groupingBy 实现多维度分组
  5. 分组转换:使用 mapping 转换元素类型
  6. 指定Map类型:使用 TreeMap 等保证顺序
  7. 聚合操作maxBy, minBy, averagingInt

这些示例涵盖了日常开发中95%以上的 groupingBy 使用场景。

抱歉,评论功能暂时关闭!