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

如何使用Java Stream找出拥有全部主商品列表商品的顾客?

用Java Stream筛选拥有全部主商品的顾客

我是Java新手,现在有两个列表:

  • 包含顾客及其购物车商品的顾客列表
  • 动态变化的主商品列表

示例对象格式

Customer列表(JSON示例)

[
{
    "customerId": 123,
    "cartItems": [
        {
            "itemId": "123-XYZ",
            "itemPrice": 200
        }, 
        {
            "itemId": "123-ABC",
            "itemPrice": 100
        }
    ]
},
{
    "customerId": 987,
    "cartItems": [
        {
            "itemId": "987-XYZ",
            "itemPrice": 200
        }
    ]
}
]

注:顾客购物车中的itemId由顾客ID与商品名通过-分隔组成。

主商品列表(JSON示例)

[
    {
        "itemName": "XYZ",
        "itemPrice": 200
    },
    {
        "itemName": "ABC",
        "itemPrice": 100
    }
]

需求

筛选出拥有主商品列表中全部商品的顾客(主商品列表是动态变化的)。我已经能用普通for循环实现(代码如下),想知道怎么用Stream函数正确解决这个问题。

原for循环实现代码

for(Customer customer: customers) {
    List<Item> items = customer.getItems();

    for(Item item: items) {
        if(item.getItemId().contains(masterListItems.getItemName()) & item.getItemPrice().equals(masterListItems.getItemPrice())) {
            System.out.println("Item found");
        }
    }
}

Stream解决方案

首先,为了高效对比,我们可以先把主商品列表转换成一个商品特征集合(用商品名和价格作为匹配依据),后续比对效率会更高。

步骤1:定义商品匹配特征类

Java 16+可以用record快速定义(自动生成equals、hashCode):

record MasterItem(String itemName, Integer itemPrice) {}

Java 16之前用普通类,需要手动重写equals和hashCode:

import java.util.Objects;

class MasterItem {
    private String itemName;
    private Integer itemPrice;

    public MasterItem(String itemName, Integer itemPrice) {
        this.itemName = itemName;
        this.itemPrice = itemPrice;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MasterItem that = (MasterItem) o;
        return Objects.equals(itemName, that.itemName) && Objects.equals(itemPrice, that.itemPrice);
    }

    @Override
    public int hashCode() {
        return Objects.hash(itemName, itemPrice);
    }
}

步骤2:将主商品列表转换为Set集合

Set<MasterItem> masterItemSet = masterList.stream()
    .map(item -> new MasterItem(item.getItemName(), item.getItemPrice()))
    .collect(Collectors.toSet());

步骤3:用Stream筛选符合条件的顾客

import java.util.stream.Collectors;

List<Customer> qualifyingCustomers = customers.stream()
    .filter(customer -> {
        // 提取顾客购物车商品的特征集合
        Set<MasterItem> customerItemSet = customer.getCartItems().stream()
            .map(cartItem -> {
                // 从itemId拆分出商品名(如"123-XYZ"拆分后取"XYZ")
                String itemName = cartItem.getItemId().split("-")[1];
                return new MasterItem(itemName, cartItem.getItemPrice());
            })
            .collect(Collectors.toSet());
        // 判断顾客是否拥有全部主商品
        return customerItemSet.containsAll(masterItemSet);
    })
    .collect(Collectors.toList());

代码说明

  1. 转主商品为Set:Set的containsAll操作效率比List高,适合动态变化的主商品列表场景。
  2. 顾客筛选逻辑:对每个顾客,先把他的购物车商品转换成MasterItem集合,再通过containsAll判断是否包含所有主商品,符合条件的顾客会被保留。
  3. itemId拆分:如果存在itemId格式异常的情况,可以加判断(比如split("-").length == 2)避免数组越界。

可选优化

如果主商品列表或顾客数量较多,建议提前缓存masterItemSet,避免重复转换,提升性能。

内容的提问来源于stack exchange,提问作者Sandy Java

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:10:32