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

支持空值多参数的Mobile搜索方法实现优化问询

嘿,这种硬编码覆盖16种参数组合的方式确实太繁琐了,不仅写起来累,后续维护或者加新参数的时候简直是噩梦!给你几个更优雅的实现思路,能彻底摆脱这种“组合地狱”:

方案1:Java Stream 流式过滤(最直接的改造)

利用Stream的filter方法,逐个对每个参数做非空判断+匹配,每个条件独立,完全不用管参数组合数。代码简洁直观,改造成本最低:

import java.util.Set;
import java.util.stream.Collectors;

public class MobileSearchService {
    public Set<Mobile> search(Set<Mobile> mobiles, OperatingSystem os, Brand brand, Display display, Style style) {
        return mobiles.stream()
            // 操作系统非空才匹配,为空则跳过该条件
            .filter(mobile -> os == null || mobile.getOperatingSystem().equals(os))
            // 品牌参数同理
            .filter(mobile -> brand == null || mobile.getBrand().equals(brand))
            // 屏幕参数同理
            .filter(mobile -> display == null || mobile.getDisplay().equals(display))
            // 风格参数同理
            .filter(mobile -> style == null || mobile.getStyle().equals(style))
            .collect(Collectors.toSet());
    }
}

这种方式的优势在于:

  • 代码线性,每个条件逻辑独立,可读性极强
  • 新增参数只需要加一行filter,完全不用考虑组合数
  • 底层Stream的并行处理还能轻松优化性能(如果数据集很大)
方案2:Predicate 组合(适合复杂条件扩展)

如果后续可能要加更复杂的搜索逻辑(比如范围查询、模糊匹配),可以把每个非空参数的判断封装成Predicate,然后统一组合过滤:

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class MobileSearchService {
    public Set<Mobile> search(Set<Mobile> mobiles, OperatingSystem os, Brand brand, Display display, Style style) {
        List<Predicate<Mobile>> predicates = new ArrayList<>();

        if (os != null) {
            predicates.add(mobile -> mobile.getOperatingSystem().equals(os));
        }
        if (brand != null) {
            predicates.add(mobile -> mobile.getBrand().equals(brand));
        }
        if (display != null) {
            predicates.add(mobile -> mobile.getDisplay().equals(display));
        }
        if (style != null) {
            predicates.add(mobile -> mobile.getStyle().equals(style));
        }

        // 所有非空条件都要满足
        return mobiles.stream()
            .filter(mobile -> predicates.stream().allMatch(pred -> pred.test(mobile)))
            .collect(Collectors.toSet());
    }
}

这种方式的好处是:

  • 每个条件逻辑被单独封装,方便复用和修改
  • 后续可以轻松添加复杂Predicate(比如mobile.getPrice() < maxPrice)
  • 还能灵活调整条件关系(比如把allMatch改成anyMatch实现“或”逻辑)
方案3:Builder模式封装搜索参数(优化调用体验)

如果参数数量还可能增加,或者想让调用方的代码更清晰,可以先把搜索参数封装成一个Builder类:

// 搜索条件封装类
public class MobileSearchCriteria {
    private OperatingSystem os;
    private Brand brand;
    private Display display;
    private Style style;

    private MobileSearchCriteria(Builder builder) {
        this.os = builder.os;
        this.brand = builder.brand;
        this.display = builder.display;
        this.style = builder.style;
    }

    // Getter方法
    public OperatingSystem getOs() { return os; }
    public Brand getBrand() { return brand; }
    public Display getDisplay() { return display; }
    public Style getStyle() { return style; }

    // Builder内部类
    public static class Builder {
        private OperatingSystem os;
        private Brand brand;
        private Display display;
        private Style style;

        public Builder os(OperatingSystem os) {
            this.os = os;
            return this;
        }

        public Builder brand(Brand brand) {
            this.brand = brand;
            return this;
        }

        public Builder display(Display display) {
            this.display = display;
            return this;
        }

        public Builder style(Style style) {
            this.style = style;
            return this;
        }

        public MobileSearchCriteria build() {
            return new MobileSearchCriteria(this);
        }
    }
}

然后改造search方法:

public class MobileSearchService {
    public Set<Mobile> search(Set<Mobile> mobiles, MobileSearchCriteria criteria) {
        return mobiles.stream()
            .filter(mobile -> criteria.getOs() == null || mobile.getOperatingSystem().equals(criteria.getOs()))
            .filter(mobile -> criteria.getBrand() == null || mobile.getBrand().equals(criteria.getBrand()))
            .filter(mobile -> criteria.getDisplay() == null || mobile.getDisplay().equals(criteria.getDisplay()))
            .filter(mobile -> criteria.getStyle() == null || mobile.getStyle().equals(criteria.getStyle()))
            .collect(Collectors.toSet());
    }
}

调用的时候就会非常清晰:

// 比如只按品牌和屏幕搜索
MobileSearchCriteria criteria = new MobileSearchCriteria.Builder()
    .brand(Brand.SAMSUNG)
    .display(Display.AMOLED)
    .build();
Set<Mobile> result = searchService.search(allMobiles, criteria);

这种方式的优势在于:

  • 避免了方法参数过多的问题,调用方代码可读性大幅提升
  • 搜索条件可以复用、修改,不用每次传一堆零散参数
  • 后续加新参数只需要在Builder里加对应方法,对现有代码侵入极小

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:39:37