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

Java Stream复杂过滤问题咨询:筛选街道含指定字符的Person

嘿,这事儿用Java Stream完全能搞定,思路和你之前用的SQL内连接其实异曲同工,我给你拆解清楚哈!

首先得先明确下POJO的结构(你没给出具体定义,我先按最常见的两种场景来演示):

场景1:Person与Address通过外键关联(对应SQL内连接的场景)

这种情况和你用SQL JOIN的逻辑最像——两个集合分别存Person和Address,Person里用addressId关联Address的id。

先定义POJO

// Person类
public class Person {
    private Long id;
    private String name;
    private Long addressId; // 关联Address的主键id

    // 构造器、getter、toString方法这里就省略啦
}

// Address类
public class Address {
    private Long id;
    private String street;
    private String city;

    // 构造器、getter、toString方法同样省略
}

模拟测试数据

import java.util.Arrays;
import java.util.List;

List<Person> personList = Arrays.asList(
    new Person(1L, "Alice", 1L),
    new Person(2L, "Bob", 2L),
    new Person(3L, "Charlie", 3L),
    new Person(4L, "David", 4L)
);

List<Address> addressList = Arrays.asList(
    new Address(1L, "Main Street", "New York"),
    new Address(2L, "Oak Avenue", "London"), // 街道含"ol"
    new Address(3L, "Maple Road", "Paris"),
    new Address(4L, "Coral Lane", "Tokyo") // 街道含"ol"
);

Stream实现方案

方案1:直接遍历匹配(小数据量友好)

这个写法最直观,直接在filter里判断当前Person对应的Address是否符合街道包含"ol"的条件:

import java.util.stream.Collectors;

List<Person> filteredPersons = personList.stream()
    .filter(person -> addressList.stream()
        // 先匹配关联的Address,再筛选街道条件
        .anyMatch(address -> address.getId().equals(person.getAddressId()) 
            && address.getStreet().contains("ol")))
    .collect(Collectors.toList());

方案2:用Map预处理(大数据量更高效)

如果你的集合数据量比较大,每次遍历addressList会有点慢,建议先把Address转成以id为key的Map,这样查找关联Address的效率会高很多:

import java.util.Map;
import java.util.Objects;
import java.util.AbstractMap;
import java.util.stream.Collectors;

// 先把Address集合转成Map,key是addressId,value是Address对象
Map<Long, Address> addressMap = addressList.stream()
    .collect(Collectors.toMap(Address::getId, address -> address));

List<Person> filteredPersons = personList.stream()
    // 把Person和对应的Address配对成Entry,没有对应Address的就设为null
    .map(person -> {
        Address address = addressMap.get(person.getAddressId());
        return address != null ? new AbstractMap.SimpleEntry<>(person, address) : null;
    })
    .filter(Objects::nonNull) // 过滤掉没有对应Address的Person(对应SQL内连接的逻辑)
    .filter(entry -> entry.getValue().getStreet().contains("ol")) // 筛选街道含"ol"的记录
    .map(AbstractMap.SimpleEntry::getKey) // 只保留Person对象
    .collect(Collectors.toList());

场景2:Person直接持有Address对象

如果你的Person类里直接包含Address属性(而不是外键),那代码会更简洁:

调整后的Person类

public class Person {
    private Long id;
    private String name;
    private Address address; // 直接持有Address对象

    // 构造器、getter、toString省略
}

Stream筛选代码

import java.util.stream.Collectors;

List<Person> filteredPersons = personList.stream()
    // 先判断Address不为空,再筛选街道包含"ol"
    .filter(person -> person.getAddress() != null 
        && person.getAddress().getStreet().contains("ol"))
    .collect(Collectors.toList());

核心思路其实就是:先把Person和对应的Address关联起来(对应SQL的JOIN操作),然后筛选出符合街道条件的记录,最后收集Person对象就好啦!

内容的提问来源于stack exchange,提问作者David Tavan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:21:36