Java 8流 - 或条件

Roc*_*der 5 java lambda java-8 java-stream

看到这段代码:(这是工作代码,但我不喜欢使用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);
Run Code Online (Sandbox Code Playgroud)

我无法想象如何使用一个OR (|)条件filter来删除两个特定元素,List因为它会给我编译时错误(在IDE中),我最终使用两个filters像上面那样.我能错过什么?

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

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

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

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

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

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

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);
    }
Run Code Online (Sandbox Code Playgroud)

krm*_*007 12

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这通常是我的首选方法。它还允许实用程序类包含用于匹配的谓词,这非常好。 (2认同)

Rol*_*and 6

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

编辑(问题详述):我仍然认为,你的情况有误.你可能想要排除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]$")
Run Code Online (Sandbox Code Playgroud)


Car*_*ate 1

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

注意第二个x->。它用于在 lambda 开头绑定变量。将其放在中间是无效的,并且没有必要,因为x范围中已经存在。只需删除该位即可:

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