Java 如何通过一个由布尔变量定义的3种过滤器类型的ArrayList进行过滤?

Java 如何通过一个由布尔变量定义的3种过滤器类型的ArrayList进行过滤?,java,arraylist,Java,Arraylist,我有主要的arraylistcars,我试图用三种不同的方式对其进行过滤。每个过滤器可以单独使用,也可以一起使用 因此,如果有三个过滤器:x、y和z,并且只有x和y为真,那么一个新的数组列表将考虑过滤器x和y,并且将显示每个条目。如果x、y和z均为真,则主数组列表“cars”将通过所有三种方法进行过滤,并将创建一个新的数组列表,然后显示所有过滤后剩下的内容 我有每个过滤器的布尔实例变量,每当调用特定过滤器的方法时,这些变量都设置为true。例如,如果我要过滤cars数组列表以查看汽车是否为电动汽

我有主要的
arraylistcars
,我试图用三种不同的方式对其进行过滤。每个过滤器可以单独使用,也可以一起使用

因此,如果有三个过滤器:x、y和z,并且只有x和y为真,那么一个新的数组列表将考虑过滤器x和y,并且将显示每个条目。如果x、y和z均为真,则主数组列表“cars”将通过所有三种方法进行过滤,并将创建一个新的数组列表,然后显示所有过滤后剩下的内容

我有每个过滤器的布尔实例变量,每当调用特定过滤器的方法时,这些变量都设置为true。例如,如果我要过滤
cars
数组列表以查看汽车是否为电动汽车,我会在
public void filterByElectric()方法的开头设置
filterElectric=true
,然后在使用for循环的地方添加代码,以检查数组列表的每个索引位置中的每个
Car
对象是否是电动的

我知道我可以简单地做一个大的if语句,它允许我说
if(filterElectric==true)
,然后显示带有过滤汽车的新数组列表,我知道我可以使用
&&
一次使用多个过滤器(如果它们为true)只需将新创建的数组列表附加在一起,并用for循环显示每个新筛选的条目,但这样做意味着我必须为所有场景设置条件

我怎样才能首先检查三个过滤器中的哪些是真的,然后在我知道哪些过滤器变量设置为真后,我可以将这两个过滤列表附加在一起以显示


公共的一切{
如果(filX==true&&filY==true&&filZ==true){
//附加所有筛选的列表,然后打印新创建的列表
//列表到系统
过滤。添加全部(filX);
过滤。添加全部(filY);
过滤。添加全部(filZ);
用于(车辆a:已过滤){
System.out.println(a.disp());
}
}else if(filX==true&&filY==true&filZ==false){
过滤。添加全部(filX);
过滤。添加全部(filY);
用于(车辆a:已过滤){
System.out.println(a.disp());
}
//然后它继续前进。。。。
//有没有更快的方法
//而不是用&&写所有条件?
}
}
公共无效筛选器x(){
filX=真;
用于(汽车a:汽车){
如果(a.getWhather()==1){
xList.添加(a);
}否则{
打破
}
}
}
公共空滤器(){
费里=真;
用于(汽车a:汽车){
如果(a.getSomething()==true){
添加(a);
}否则{
打破
}
}
}
公共无效filZ(双a,双b){
filZ=真;
用于(汽车a:汽车){
如果(a.getP()>=a&&a.getP()快速解决方案,这可能就是您要寻找的

从汽车开始:

package so.car;

public class Car {
    private String name;
    private boolean electric;
    private boolean awd;
    private boolean automatic;

    public Car(String name, boolean electric, boolean awd, boolean automatic) {
        this.name = name;
        this.electric = electric;
        this.awd = awd;
        this.automatic = automatic;
    }

    public boolean isElectric() {
        return electric;
    }

    public void setElectric(boolean electric) {
        this.electric = electric;
    }

    public boolean isAwd() {
        return awd;
    }

    public void setAwd(boolean awd) {
        this.awd = awd;
    }

    public boolean isAutomatic() {
        return automatic;
    }

    public void setAutomatic(boolean automatic) {
        this.automatic = automatic;
    }

    @Override
    public String toString() {
        return "Car [name=" + name + "]";
    }

}
然后,需要处理同时运行多个过滤器的问题:

package so.car;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

public class CarFilters {
    private Map<String, Function<Car, Boolean>> filters;

    public CarFilters(Map<String, Function<Car, Boolean>> filters) {
        this.filters = filters;
    }

    public List<String> getPassingFilterNames(Car car) {
        List<String> passingFilterNames = new ArrayList<>();

        for (Entry<String, Function<Car, Boolean>> entry : filters.entrySet()) {
            String filterName = entry.getKey();
            Function<Car, Boolean> predicateFunction = entry.getValue();

            if (predicateFunction.apply(car)) {
                passingFilterNames.add(filterName);
            }
        }

        return passingFilterNames;
    }
}

您可以基于要应用的过滤逻辑构建谓词,并仅使用此谓词过滤流:

     public Predicate<Car> filter = car ->  {
        boolean filter = true;

        if (isfilterEletricOn()) {
            filter = filter && car.isEletric();
        }

        if (isfilterOffRoadOn()) {
            filter = filter && car.isOffRoad();
        }

        if (isfilterSportOn()) {
            filter = filter && car.isSport();
        }

        return filter;
    };

    cars.stream().filter(filter).collect(Collectors.toList());
公共谓词过滤器=car->{
布尔过滤器=真;
if(isFilterRetricon()){
filter=filter&car.isEletric();
}
如果(isfilterOffRoadOn()){
过滤器=过滤器&car.isofroad();
}
if(isfilterSportOn()){
filter=filter&car.isSport();
}
回流过滤器;
};
cars.stream().filter(filter.collect(collector.toList());

您可以执行以下操作:

public static Predicate<Car> filteringAll(boolean filterToyota, boolean filterAudi) {
        return p -> (p.getManufacturer().getName().equals("Toyota") && filterToyota) || (p.getManufacturer().getName().equals("Audi") && filterAudi);
    }
List<Car> listOfFilteredCars = listOfCars.stream().filter(filteringAll(false, true)).collect(Collectors.toList());

制造商类别


如果希望代码尽可能短,可以这样做:

public static List<Car> filter(
    List<Car> allCars,
    boolean onlyElectric,
    boolean onlyAllWheelsDrive,
    boolean onlyAutomatic)
{
    return allCars.stream()
        .filter((Car car) -> !onlyElectric || car.isElectric())
        .filter((Car car) -> !onlyAllWheelsDrive|| car.isAllWheelsDrive())
        .filter((Car car) -> !onlyAutomatic|| car.isAutomatic())
        .collect(Collectors.toList());
}
filter(allCars, CarFilter.Electric, CarFilter.Automatic);
这可以更容易地翻译成人类可以理解的语言:如果选择了“onlyElectric”过滤器,检查汽车是否真的是电动的。如果没有选择,只需返回true,这意味着过滤器接受每辆汽车

在您编写这段代码的时候,它将是有意义的。几天后,当您回来添加另一个过滤器时,您可能会问自己:3个布尔参数中的哪一个是哪一个,为什么它们的顺序正好如此?另一种解决方案是使用
enum
而不是这些布尔值

public enum CarFilter {
    Electric, AllWheelsDrive, Automatic
}

public static List<Car> filter(
    List<Car> allCars,
    CarFilter... filters)
{
    EnumSet<CarFilter> set = EnumSet.noneOf(CarFilter.class);
    Collections.addAll(set, filters);

    return allCars.stream()
        .filter((Car car) -> !set.contains(CarFilter.Electric) || car.isElectric())
        .filter((Car car) -> !set.contains(CarFilter.AllWheelsDrive) || car.isAllWheelsDrive())
        .filter((Car car) -> !set.contains(CarFilter.Automatic) || car.isAutomatic())
        .collect(Collectors.toList());
}
此代码包含的信息肯定比:

filter(allCars, true, false, true);

对于更动态的解决方案,您可以创建一个
MyFilter
类,该类具有
active
属性和
filter
谓词:

public class MyFilter<T> {
    private boolean isActive;
    private Predicate<T> filter;
    // constructor and/or getter and setter
}
并使用以下内容筛选您的列表:

List<MyObject> result = objects.stream()
        .filter(o -> filters.stream().allMatch(f -> f.test(o)))
        .collect(Collectors.toList());
List result=objects.stream()
.filter(o->filters.stream().allMatch(f->f.test(o)))
.collect(Collectors.toList());

如果您只想匹配一个筛选器,可以使用
anyMatch
而不是
allMatch
。要否定结果,可以使用
noneMatch

发布一些伪代码吗?如果您关心短而漂亮的代码,请使用kotlin。您可以使用列表上的筛选器或smth。例如,选中此项nna现在编辑问题。看看我的例子,@ardzy
    .filter((Car car) -> onlyElectric ? car.isElectric() : true)
public enum CarFilter {
    Electric, AllWheelsDrive, Automatic
}

public static List<Car> filter(
    List<Car> allCars,
    CarFilter... filters)
{
    EnumSet<CarFilter> set = EnumSet.noneOf(CarFilter.class);
    Collections.addAll(set, filters);

    return allCars.stream()
        .filter((Car car) -> !set.contains(CarFilter.Electric) || car.isElectric())
        .filter((Car car) -> !set.contains(CarFilter.AllWheelsDrive) || car.isAllWheelsDrive())
        .filter((Car car) -> !set.contains(CarFilter.Automatic) || car.isAutomatic())
        .collect(Collectors.toList());
}
filter(allCars, CarFilter.Electric, CarFilter.Automatic);
filter(allCars, true, false, true);
public class MyFilter<T> {
    private boolean isActive;
    private Predicate<T> filter;
    // constructor and/or getter and setter
}
List<MyFilter<MyObject>> filters = Arrays.asList(
        new MyFilter<>(true, MyObject::isA),
        new MyFilter<>(false, MyObject::isB),
        new MyFilter<>(true, MyObject::isC)
);
List<MyObject> result = objects.stream()
        .filter(o -> filters.stream().filter(MyFilter::isActive).allMatch(f -> f.getFilter().test(o)))
        .collect(Collectors.toList());
public boolean test(T object) {
    return !isActive || filter.test(object);
}
List<MyObject> result = objects.stream()
        .filter(o -> filters.stream().allMatch(f -> f.test(o)))
        .collect(Collectors.toList());