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

Java如何过滤嵌套列表?筛选不含用户过敏原的食谱列表

过敏原食谱过滤实现方案

核心判断规则:只要食谱关联的任意一个产品,包含用户过敏原列表里的任意一种过敏原,该食谱就不符合要求;只有所有产品的所有过敏原都和用户过敏原列表无交集,才会被保留。

前置注意事项

  • 先确保Alergen类正确重写了equals()和hashCode()方法,如果是根据过敏原id或者名称做唯一判定,也可以在比对时直接取对应属性判断,避免同内容不同对象导致的判断错误。
  • 提前处理空值边界:比如入参为空、食谱未关联产品、产品未标注过敏原的场景,避免空指针异常。

代码实现(Java)

为了提升判断效率,先把用户传入的过敏原列表转为HashSet,把存在性判断的时间复杂度从List的O(n)降到O(1),同时利用短路判断逻辑,只要发现第一个匹配的过敏原就终止当前食谱的校验,减少无效计算。

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

public class RecipeFilterService {

    public List<Recipe> getSafeRecipes(List<Recipe> sourceRecipes, List<Alergen> userAlergens) {
        // 处理空入参
        if (sourceRecipes == null || sourceRecipes.isEmpty()) {
            return Collections.emptyList();
        }
        Set<Alergen> userAlergenSet = userAlergens == null ? Collections.emptySet() : new HashSet<>(userAlergens);
        // 用户无过敏原时直接返回全部食谱
        if (userAlergenSet.isEmpty()) {
            return sourceRecipes;
        }

        return sourceRecipes.stream()
                .filter(recipe -> isRecipeSafeForUser(recipe, userAlergenSet))
                .collect(Collectors.toList());
    }

    private boolean isRecipeSafeForUser(Recipe recipe, Set<Alergen> userAlergenSet) {
        List<Product> products = recipe.getProducts();
        // 未关联产品的食谱默认安全
        if (products == null || products.isEmpty()) {
            return true;
        }
        
        // 遍历所有产品,只要发现一个匹配过敏原就直接返回不安全
        for (Product product : products) {
            List<Alergen> productAlergens = product.getAlergens();
            if (productAlergens == null || productAlergens.isEmpty()) {
                continue;
            }
            for (Alergen alergen : productAlergens) {
                if (userAlergenSet.contains(alergen)) {
                    return false;
                }
            }
        }
        return true;
    }
}

如果偏好更简洁的Stream写法,可以把判断逻辑直接用noneMatch实现,效果完全一致,noneMatch本身自带短路判断逻辑:

// 替换上面filter里的方法引用即可
.filter(recipe -> {
    List<Product> products = recipe.getProducts();
    if (products == null || products.isEmpty()) {
        return true;
    }
    return products.stream()
            .map(Product::getAlergens)
            .filter(Objects::nonNull)
            .flatMap(List::stream)
            .noneMatch(userAlergenSet::contains);
})

逻辑说明

  • 所有空场景都做了兼容,不会因为缺字段抛出空指针
  • 用HashSet存储用户过敏原,大数据量下判断性能远高于直接遍历List
  • 短路判断逻辑避免遍历不必要的数据,执行效率更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:48:27