8

I am moving to use Java11. Learning a new method Predicate.not, I found my current code to find only cat family as:

List<String> animals = List.of("cat", "leopard", "dog", "lion", "horse");
Predicate<String> cats = a -> !a.equals("dog") && !a.equals("horse");
Set<String> filterCat = animals.stream().filter(cats).collect(Collectors.toSet());
System.out.println(filterCat);

output is :

leopard, cat, lion

Now I am trying to use the new method and the output is coming incorrect. How do I correct it? What did I do wrong?

My later code:

Predicate<String> updatedCatFilter = Predicate.not(a -> a.equals("dog") && a.equals("horse"));
Set<String> catFamily = animals.stream().filter(updatedCatFilter).collect(Collectors.toSet());
System.out.println(filterCat);

But this outputs all my list now.

horse, leopard, cat, dog, lion

Naman
  • 27,789
  • 26
  • 218
  • 353
Mani
  • 1,068
  • 3
  • 13
  • 27

2 Answers2

14

What did I do wrong?

You seem to be missing the basic De-morgan's laws which states that

!(a || b) == !a && !b

and

!(a && b) == !a || !b

How do I correct it?

So you should change your code to use

Predicate.not(a -> a.equals("dog") || a.equals("horse")); // !(a || b)

which shall be equivalent to your existing code

Predicate<String> cats = a -> !a.equals("dog") && !a.equals("horse");

that can also be looked upon as:

Predicate<String> notDog = a -> !a.equals("dog");
Predicate<String> notHorse =  a -> !a.equals("horse");
Predicate<String> cats = notDog.and(notHorse); // !a && !b
Naman
  • 27,789
  • 26
  • 218
  • 353
0

You can write it in that way:

List<String> animals = List.of("cat", "leopard", "dog", "lion", "horse");
Set<String> filterCat = animals.stream()
    .filter(Predicate.not("dog"::equals).and(Predicate.not("horse"::equals)))
    .collect(Collectors.toSet());
System.out.println(filterCat);
lczapski
  • 4,026
  • 3
  • 16
  • 32