Rockoder
Rockoder

Reputation: 794

Java 8 stream - or condition

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)

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 filter to remove two specific elements from List since it would give me compile time error (in IDE) and I end up using two filters like above. What could I be missing?

This is how I tried to use 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)

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

Upvotes: 10

Views: 34928

Answers (5)

user1214683
user1214683

Reputation: 9

   Question is "filter out with certain condition from Male or Female with one line"
    with consumer implementation for printing
    Answer
    --------
    public class Emp{
         private String name;
         private int age;
         private String gender; with setter, getter Allargument constructor}
    
    public class MailFemaleFilter {
        public static void main(String[] args) {
            List<Emp> empli=new ArrayList<Emp>();
            empli.add(new Emp("A",33,"m"));
            empli.add(new Emp("B",26,"m"));
            empli.add(new Emp("C",18,"m"));
            empli.add(new Emp("D",90,"m"));
            empli.add(new Emp("E",45,"m"));
            
            //female
            empli.add(new Emp("A1",7,"f"));
            empli.add(new Emp("B1",29,"f"));
            empli.add(new Emp("C1",70,"f"));
            empli.add(new Emp("D1",23,"f"));
            empli.add(new Emp("E1",39,"f"));
    //creation of predicate
    Predicate<Emp> agetest =  e-> e.getAge() > 30;
            Predicate<Emp> genderMtest =  m-> m.getGender().equals("m");
            Predicate<Emp> genderFtest =  mf-> mf.getGender().equals("f");
        List<Emp> FilteredEmp=empli.stream().filter(agetest.and((genderMtest).or(genderFtest)))
    .collect(Collectors.toList());  
    
    //printing by consumer
    
     MyConsumer action = new MyConsumer();
            FilteredEmp.forEach(action);
                    
            
        }
    
    }
    //creation of consumer implementation 
    class MyConsumer implements Consumer<Emp>{
    
        public void accept(Emp t) {
            System.out.println("Consumer impl name of emp ::"+t.getName()+":: with respective gender ::"
                    +t.getGender());
        }
    }

Upvotes: 0

avi.elkharrat
avi.elkharrat

Reputation: 6808

I have had a similar question: how to use Java streams to filter a subset of objects that satisfy CONDITION_1 OR CONDITION_2. I figured out it would be to include both conditions in the filter.

myListOfElms().stream()
  .filter(elm -> elm.condition1OK() || elm.condition2OK())
  .collect(toList());

Of course wrapping these conditions in a private method would make it look better. But that's the idea.

Upvotes: 0

Manish Kumar
Manish Kumar

Reputation: 7189

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

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

Upvotes: 26

Roland
Roland

Reputation: 23352

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.

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

!(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]$")

Upvotes: 6

Carcigenicate
Carcigenicate

Reputation: 45826

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 x already exists in the scope. Just remove that bit:

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

Upvotes: 1

Related Questions