java - 如何通过 boolean 变量定义的 3 种过滤器类型来过滤 ArrayList?

标签 java arraylist

我有主要的ArrayList<Car> cars我正在尝试以三种不同的方式进行过滤。每个过滤器可以单独使用,也可以一起使用。

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

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

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

我如何能够首先检查三个过滤器中的哪些为真,然后在知道哪些过滤器变量设置为 true 后,我可以将这两个过滤列表附加在一起以进行显示?


    public void displayEverything() {
    if (filX == true && filY == true && filZ == true) {
        // append all filtered lists and then print newly created
        // list to system

        filtered.addAll(filX);
        filtered.addAll(filY);
        filtered.addAll(filZ);

        for (Car a : filtered) {
            System.out.println(a.disp());
        }

    } else if (filX == true && filY == true & filZ == false) {
        filtered.addAll(filX);
        filtered.addAll(filY);

        for (Car a : filtered) {
            System.out.println(a.disp());
        }
        // then it keeps going.... 
        // is there a faster way to do this 
        // instead of writing all conditions with &&'s?
    }
}


public void filterX() {
    filX = true;

    for (Car a : cars) {
        if (a.getWhatever() == 1) {
            xList.add(a);
        } else {
            break;
        }
    }
}

public void filterY() {
    filY = true;

    for (Car a : cars) {
        if (a.getSomething() == true) {
            yList.add(a);
        } else {
            break;
        }
    }
}

public void filZ(double a, double b) {
    filZ = true;

    for (Car a : cars) {
        if (a.getP() >= a && a.getP() <= b) {
            zList.add(a);
        } else {
            break;
        }
    }
}

最佳答案

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

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());
}

!onlyElectric || ... 乍一看有点奇怪。可以用另一种方式编写:

    .filter((Car car) -> onlyElectric ? car.isElectric() : true)

这可以更容易地翻译成人类可以理解的语言:如果选择“onlyElectric”过滤器,请检查汽车是否真的是电动的。如果没有选择,则返回true,这意味着过滤器接受每辆车。

当你编写这段代码时,它就会有意义。几天后,当您回来添加另一个过滤器时,您可能会问自己:3 个 boolean 参数中的哪一个是哪个,为什么它们严格按照这个顺序?另一种解决方案是使用枚举而不是这些 boolean 值。

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);

关于java - 如何通过 boolean 变量定义的 3 种过滤器类型来过滤 ArrayList?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55327261/

相关文章:

Android - 将值从 sqlite 数据库加载到 arraylist

java - 扫描仪没有停止

java - 圆角半径可绘制形状

java - 使用FTP测试文件上传和下载速度

Java - 如何增加 JFileChooser 中文件夹名称的字体?

java - arraylist 的质量变化值

java - 在列表最佳解决方案中查找给定数字的出现次数

java - java.util.Arrays.asList(T...) 是如何工作的?

Java函数式-反转ANY对象的ANY列表类型

java - 将 int 转换为 String 是否算作自动装箱?