You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8中如何根据id字段获取两个Person列表的匹配子集?

最优解决方案:利用Stream API + HashSet 实现高效匹配

这是个很典型的集合匹配场景,在Java 8里我们可以通过先预存匹配标识+Stream过滤的组合来实现最优性能的匹配,下面具体拆解实现思路和代码:

核心思路:用HashSet降低匹配成本

直接嵌套遍历两个列表做匹配的时间复杂度是O(n*m),当数据量变大时会很慢。我们可以先把ages里的所有id提取到HashSet中(HashSet的contains()方法是O(1)时间复杂度),再用Stream过滤persons,这样整体时间复杂度能降到O(n+m),效率提升非常明显。

具体代码实现

1. 提取ages中的id到HashSet

Set<String> matchedIds = ages.stream()
                            .map(Person::getId)
                            .collect(Collectors.toSet());

2. 过滤persons得到匹配子集

List<Person> result = persons.stream()
                            .filter(person -> matchedIds.contains(person.getId()))
                            .collect(Collectors.toList());

完整可运行示例

import lombok.Builder;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Getter
@Builder
class Person {
    private String id;
    private String name;
    private Integer age;
}

public class PersonMatchDemo {
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        persons.add(Person.builder().id("001").name("alpha").build());
        persons.add(Person.builder().id("002").name("beta").build());
        persons.add(Person.builder().id("003").name("gamma").build());

        List<Person> ages = new ArrayList<>();
        ages.add(Person.builder().id("001").age(25).build());
        ages.add(Person.builder().id("002").age(40).build());

        // 预存需要匹配的id集合
        Set<String> matchedIds = ages.stream()
                                    .map(Person::getId)
                                    .collect(Collectors.toSet());

        // 筛选出匹配的Person子集
        List<Person> matchedPersons = persons.stream()
                                            .filter(p -> matchedIds.contains(p.getId()))
                                            .collect(Collectors.toList());

        // 打印验证结果
        matchedPersons.forEach(p -> System.out.printf("ID: %s, Name: %s%n", p.getId(), p.getName()));
        // 输出:
        // ID: 001, Name: alpha
        // ID: 002, Name: beta
    }
}

补充说明

如果你的需求不仅是筛选子集,还需要把ages里的age属性合并到persons的对应对象中,可以在过滤后再做一步属性赋值,比如:

List<Person> mergedPersons = persons.stream()
                                    .filter(p -> matchedIds.contains(p.getId()))
                                    .map(p -> {
                                        // 找到对应的age对象
                                        Person ageObj = ages.stream()
                                                            .filter(a -> a.getId().equals(p.getId()))
                                                            .findFirst()
                                                            .orElse(null);
                                        // 合并属性,这里需要注意Person是不可变类的话要重新build
                                        return Person.builder()
                                                    .id(p.getId())
                                                    .name(p.getName())
                                                    .age(ageObj != null ? ageObj.getAge() : null)
                                                    .build();
                                    })
                                    .collect(Collectors.toList());

内容的提问来源于stack exchange,提问作者Abhi Nandan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:38:34