Skip to content
Advertisement

Unable to get my head around Predicate isEqual method

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 Predicates, 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();
Advertisement