Java 8 流 - 或条件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40551216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:18:54  来源:igfitidea点击:

Java 8 stream - or condition

javalambdajava-8java-stream

提问by Rockoder

See this code: (This is working code but I don't like to use 2 lines so looking for how can I make it better)

请参阅此代码:(这是工作代码,但我不喜欢使用 2 行,因此正在寻找如何使其更好)

ItemDetails[] items = response.getDetailsList();
items = Arrays.stream(items).filter(x -> !x.getName().equalsIgnoreCase("acl1")).toArray(ItemDetails[]::new);
items = Arrays.stream(items).filter(x -> !x.getName().equalsIgnoreCase("acl2")).toArray(ItemDetails[]::new);

I could not figure how to use an OR (|)condition within filterto remove two specific elements from Listsince it would give me compile time error (in IDE) and I end up using two filterslike above. What could I be missing?

我无法弄清楚如何使用其中的OR (|)条件filter来从中删除两个特定元素,List因为它会给我编译时错误(在 IDE 中)并且我最终使用了filters上面的两个。我可能会错过什么?

This is how I tried to use OR

这就是我尝试使用 OR 的方式

items = Arrays.stream(items).filter(x -> !x.getName().equalsIgnoreCase("acl1") ||
        x -> !x.getName().equalsIgnoreCase("acl2")).toArray(ItemDetails[]::new);

=> IntelliJ would complain about this one (above)

=> IntelliJ 会抱怨这个(上图)

items = Arrays.stream(items).filter(x -> !x.getName().equalsIgnoreCase("acl1"") ||
        x.getName().equalsIgnoreCase("acl2")).toArray(ItemDetails[]::new);

Does not work at runtime (it does not filter)

在运行时不起作用(它不过滤)

Entire code with commented code (which I tried) for reference

带有注释代码(我尝试过)的整个代码以供参考

public static void mapTest () {

        AclDetailItem[] items = new AclDetailItem[3];

        AclDetailItem item1 = new AclDetailItem();
        item1.setAclName("acl1");

        AclDetailItem item2 = new AclDetailItem();
        item2.setAclName("acl2");

        AclDetailItem item3 = new AclDetailItem();
        item3.setAclName("acl3");

        items[0] = item1;
        items[1] = item2;
        items[2] = item3;

        System.out.println ("Before " + items.length);


        items = Arrays.stream(items).filter(x -> !x.getAclName().equalsIgnoreCase("acl1")).toArray(ItemDetails[]::new);
        items = Arrays.stream(items).filter(x -> !x.getAclName().equalsIgnoreCase("acl2")).toArray(ItemDetails[]::new);

        System.out.println ("After "  + items.length);
    }

回答by krmanish007

You should create multiple predicates for each condition and join it using or. I have added my below example:

您应该为每个条件创建多个谓词并使用 or 连接它。我添加了以下示例:

public class MeTest {

    Predicate<Integer> con1 = i -> i==0;
    Predicate<Integer> con2 = i -> i==1;
    Predicate<Integer> con3 = i -> i==2;

    @Test
    public void testOr() {
        List<Integer> asdas = IntStream.range(1, 10).boxed().filter(con1.or(con2).or(con3)).collect(toList());
        System.out.println("asdas = " + asdas);
    }
}

回答by Roland

The first one is incorrect as it has a x ->too much. The second one does not filter as you constructed a condition that is always true. Just refine your condition in the filter-method and it will filter.

第一个不正确,因为它有x ->太多。第二个不会过滤,因为您构建了一个始终为 的条件true。只需在filter-method 中优化您的条件,它就会进行过滤。

EDIT (as the question got detailed): I still think, you have an error in your condition. You probably want to exclude both acl1and acl2. If so, your condition should rather look something like:

编辑(随着问题的详细化):我仍然认为,您的情况有误。您可能想同时排除acl1acl2。如果是这样,您的情况应该类似于:

!(x.getAclName().equalsIgnoreCase("acl1") || x.getAclName().equalsIgnoreCase("acl2"))
// or if you prefer &&
!x.getAclName().equalsIgnoreCase("acl1") && !x.getAclName().equalsIgnoreCase("acl2")
// or if you prefer regular expressions/matches
!x.getAclName().matches("(?i)^acl[1|2]$")

回答by Carcigenicate

items = Arrays.stream(items).filter(
    x -> !x.getName().equalsIgnoreCase("redirect")
    || x->!x.getName().equalsIgnoreCase("success"))
    .toArray(ItemDetails[]::new);

Note the second x->. That's used to bind a variable at the start of a lambda. Putting it in the middle is invalid, and unnecessary since xalready exists in the scope. Just remove that bit:

注意第二个x->。这用于在 lambda 的开头绑定一个变量。把它放在中间是无效的,而且没有必要,因为它x已经存在于作用域中。只需删除那一点:

items = Arrays.stream(items).filter(x ->
    !x.getName().equalsIgnoreCase("redirect")
    || !x.getName().equalsIgnoreCase("success"))
    .toArray(ItemDetails[]::new);