In Java docs it is given –
Modifier and Type Method and Description static <T> Predicate<T> isEqual(Object targetRef) Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
In https://www.geeksforgeeks.org/java-8-predicate-with-examples/
it is given –
isEqual(Object targetRef) : Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
static Predicate isEqual(Object targetRef) Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object). T : the type of arguments to the predicate Parameters: targetRef : the object reference with which to compare for equality, which may be null Returns: a predicate that tests if two arguments are equal according to Objects.equals(Object, Object)
I can’t get a grisp of what this Objects.equals(Object, Object)
might be
I write the following code to try it out –
Class Fruits –
Fruits.java
–
public class Fruits { private String fruit; public Fruits(String fruit) { this.fruit = fruit; } public String getFruit() { return fruit; } }
Here, the other methods of predicate seem to be quite easy to understand –
Predicate<List<Fruits>> containsApple = list -> { boolean myReturn = false; Iterator<Fruits> iterator = list.iterator(); while (iterator.hasNext()) { Fruits fruits = iterator.next(); String fruit = fruits.getFruit(); if (fruit.equals("Apple")) { myReturn = true; break; } } return myReturn; };
Predicate<List<Fruits>> containsOrange = list -> { boolean myReturn = false; Iterator<Fruits> iterator = list.iterator(); while (iterator.hasNext()) { Fruits fruits = iterator.next(); String fruit = fruits.getFruit(); if (fruit.equals("Orange")) { myReturn = true; break; } } return myReturn; };
Predicate<List<Fruits>> containsAppleAndOrange = list -> { return containsApple.and(containsOrange).test(list); };
Predicate<List<Fruits>> containsAppleOrRange = list -> { return containsApple.or(containsOrange).test(list); };
Predicate<List<Fruits>> notContainsApple = list -> { return containsApple.negate().test(list); };
Predicate<List<Fruits>> notContainsOrange = list -> { return containsOrange.negate().test(list); };
Predicate<List<Fruits>> notContainsAppleAndOrange = list -> { return containsAppleAndOrange.negate().test(list); };
Predicate<List<Fruits>> notContainsAppleOrOrange = list -> { return containsAppleOrRange.negate().test(list); };
Here I test it with following data –
List<Fruits> list1 = new ArrayList<>(List.of( new Fruits("Apple"), new Fruits("Orange"), new Fruits("Mango"), new Fruits("Banana") )); List<Fruits> list2 = new ArrayList<>(List.of( new Fruits("Apple"), new Fruits("Mango"), new Fruits("Banana"), new Fruits("Berry") )); List<Fruits> list3 = new ArrayList<>(List.of( new Fruits("Orange"), new Fruits("Mango"), new Fruits("Banana"), new Fruits("Berry") ));
Result is as expected.
But in no way can I understand how to implement the isEqual()
method –
To see that two arguments are equal are not I create another predicate –
redicate<List<Fruits>> containsApple2 = list -> { boolean myReturn = false; Iterator<Fruits> iterator = list.iterator(); while (iterator.hasNext()) { Fruits fruits = iterator.next(); String fruit = fruits.getFruit(); if (fruit.equals("Apple")) { myReturn = true; break; } } return myReturn; };
I try something like (without understanding why) –
System.out.println(Predicate.isEqual(containsApple).test(list1));
Output – false
Now what happened here?
System.out.println(Predicate.isEqual(containsApple2).test(containsApple));
Output – false
Now again what happened here?
So, how to exactly use this isEqual
method?
Advertisement
Answer
Predicate.isEqual
is a factory method that creates predicates that test if a given thing is equal to the parameter passed in.
Predicate.isEqual(containsApple)
creates a Predicate<Predicate<List<Fruits>>>
that tests if a given thing is equal to containsApple
. However, since containsApple
refers to an instance created from a lambda, and nothing much is guaranteed about the equality of instances created from lambda expressions (See the JLS), nothing much can be said about the result of calling test
on it. The classes of the lambda instances may or may not implement equals
, and containsApple
may or may not be the same instance as containsApple2
, depending on the implementation.
Rather than comparing lambda instances, a typical example of using Predicate.isEqual
is:
Fruits apple = new Fruits("Apple"); Predicate<Fruits> isApple = Predicate.isEqual(apple); // rather than this slightly longer version: // Predicate<Fruits> isApple = x -> Objects.equals(x, apple);
Then you can pass isApple
around, to other methods that take Predicate
s, and/or call test
on it. isApple.test(apple)
would be true, isApple.test(new Fruits("something else"))
would be false. I would also recommend that you override equals
and hashCode
in Fruits
.
Note that we generally make predicates that test against individual objects, rather than lists (collections) of things. We would pass these predicates to other methods (such as Stream.filter
), and let them do the filtering. For example, to filter a list to get all the apples:
List<Fruits> apples = fruitsList.stream() .filter(Predicate.isEqual(apple)).toList();