Java 8 中 List 分组的全面指南

在 Java 8 中,Stream API 提供了强大的功能来处理集合数据,其中包括对 List 进行分组操作。通过使用 Collectors.groupingBy,可以轻松地将 List 中的元素按照某个条件分组。本文将详细介绍如何使用 Java 8 对 List 进行分组,并提供多种示例代码。

1. 使用 Collectors.groupingBy 进行分组
Collectors.groupingBy 是 Java 8 中最常用的分组方法。它可以将 List 中的元素按照指定的条件分组,并返回一个 Map,其中键是分组的条件,值是对应的元素列表。

1.1 基本分组
假设有一个 List,需要按照 Person 的 city 属性进行分组。

import java.util.*;
import java.util.stream.Collectors;

class Person {
    String name;
    String city;

    Person(String name, String city) {
        this.name = name;
        this.city = city;
    }

    String getCity() {
        return city;
    }

    @Override
    public String toString() {
        return name + " (" + city + ")";
    }
}

public class GroupingExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", "New York"),
            new Person("Bob", "Los Angeles"),
            new Person("Charlie", "New York"),
            new Person("David", "Los Angeles")
        );

        // 按照 city 分组
        Map<String, List<Person>> peopleByCity = people.stream()
            .collect(Collectors.groupingBy(Person::getCity));

        // 输出分组结果
        peopleByCity.forEach((city, list) -> {
            System.out.println("City: " + city);
            list.forEach(System.out::println);
        });
    }
}

输出:

City: New York
Alice (New York)
Charlie (New York)
City: Los Angeles
Bob (Los Angeles)
David (Los Angeles)

1.2 分组后统计数量
可以使用 Collectors.counting() 统计每个分组的元素数量。

Map<String, Long> countByCity = people.stream()
    .collect(Collectors.groupingBy(Person::getCity, Collectors.counting()));

countByCity.forEach((city, count) -> {
    System.out.println("City: " + city + ", Count: " + count);
});

输出:

City: New York, Count: 2
City: Los Angeles, Count: 2

2. 多级分组
Collectors.groupingBy 支持多级分组,即按照多个条件进行分组。

2.1 示例
假设需要按照 city 和 name 的首字母进行分组。

Map<String, Map<Character, List<Person>>> peopleByCityAndInitial = people.stream()
    .collect(Collectors.groupingBy(Person::getCity,
        Collectors.groupingBy(p -> p.name.charAt(0))));

peopleByCityAndInitial.forEach((city, map) -> {
    System.out.println("City: " + city);
    map.forEach((initial, list) -> {
        System.out.println("  Initial: " + initial);
        list.forEach(System.out::println);
    });
});

输出:

City: New York
  Initial: A
Alice (New York)
  Initial: C
Charlie (New York)
City: Los Angeles
  Initial: B
Bob (Los Angeles)
  Initial: D
David (Los Angeles)

3. 分组后对值进行操作
可以对分组后的值进行进一步操作,例如求和、求平均值等。

3.1 示例
假设有一个 List,需要按照 customer 分组,并计算每个客户的总订单金额。

import java.util.*;
import java.util.stream.Collectors;

class Order {
    String customer;
    double amount;

    Order(String customer, double amount) {
        this.customer = customer;
        this.amount = amount;
    }

    String getCustomer() {
        return customer;
    }

    double getAmount() {
        return amount;
    }
}

public class GroupingExample {
    public static void main(String[] args) {
        List<Order> orders = Arrays.asList(
            new Order("Alice", 100.0),
            new Order("Bob", 200.0),
            new Order("Alice", 150.0),
            new Order("Bob", 300.0)
        );

        // 按照 customer 分组,并计算总金额
        Map<String, Double> totalAmountByCustomer = orders.stream()
            .collect(Collectors.groupingBy(Order::getCustomer,
                Collectors.summingDouble(Order::getAmount)));

        totalAmountByCustomer.forEach((customer, total) -> {
            System.out.println("Customer: " + customer + ", Total Amount: " + total);
        });
    }
}

输出:

Customer: Alice, Total Amount: 250.0
Customer: Bob, Total Amount: 500.0

4. 自定义分组逻辑
可以通过自定义 Collector 实现更复杂的分组逻辑。

4.1 示例
假设需要将 List 按照 city 分组,并将每个城市的 Person 名称拼接成一个字符串。

Map<String, String> namesByCity = people.stream()
    .collect(Collectors.groupingBy(Person::getCity,
        Collectors.mapping(Person::getName, Collectors.joining(", "))));

namesByCity.forEach((city, names) -> {
    System.out.println("City: " + city + ", Names: " + names);
});

输出:

City: New York, Names: Alice, Charlie
City: Los Angeles, Names: Bob, David

5. 总结
Java 8 的 Stream API 和 Collectors.groupingBy 提供了强大的功能,可以轻松地对 List 进行分组操作。以下是本文的主要内容:

  • 使用 Collectors.groupingBy 进行基本分组。
  • 多级分组。
  • 分组后对值进行操作(如统计数量、求和等)。
  • 自定义分组逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幻南瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值