Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meaning and usage of Predicates Java 8

I was learning the concepts of functional interfaces, lambda expression and predicates. I could write a program using examples on the internet but I am still not clear with certain constructs.

This is my class Employee with 3 data members, a constructor and corresponding setters & getters.

package lambdaandrelated;

public class Employee {

    private String name;

    private String gender;

    private int age;

    public Employee(String name, String gender, int age) {
        super();
        this.name = name;
        this.gender = gender;
        this.age = age;
    }



    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

This is another class that has got 3 methods to check:

a. whether the employee is a male. b. whether the employee is a female. c. whether the age of the employee is greater than the age passed.

package lambdaandrelated;

import java.util.function.Predicate;

    public class EmployeePredicates {

        public static Predicate<Employee> isMale(){
            return emp -> emp.getGender().equalsIgnoreCase("Male");  - **Line 1**
        }

        public static Predicate<Employee> isFemale(){
            return emp -> emp.getGender().equalsIgnoreCase("Female");
        }

        public Predicate<Employee> isGreaterThan(Integer age){
            return emp -> emp.getAge()>age;
        }
    }

This is my main class:

package lambdaandrelated;

import java.util.function.Predicate;

public class EmployeeMain {

    public static void main(String[] args) {
        Employee emp1 = new Employee("Parul", "Female", 24);
        Employee emp2 = new Employee("Kanika", "Female", 24);
        Employee emp3 = new Employee("Sumit", "Male", 27);


        Predicate<Employee> predicate1 = new EmployeePredicates().isGreaterThan(23);
        System.out.println(predicate1);  **Line2**
        boolean value = predicate1.test(emp3);
        System.out.println(value);

        boolean value1 = predicate1.negate().test(emp3);  **Line3**
        System.out.println(value1);

        System.out.println(predicate1.negate()); **Line4**



    }
}

My doubts :

1) Is Line 1 the implementation of test() method of Predicate interface? If yes, why is the return type of method isMale() a Predicate<Employee> and not a boolean?

2) The o/p of Line 2 i.e the value of variable 'predicate1' is " lambdaandrelated.EmployeePredicates$$Lambda$1/746292446@4617c264 ". But the variable 'predicate1' is of type Predicate<Employee>. What is happening in the background here?

3) What do we mean by negation of a Predicate? If it means negating the boolean o/p, then should it not be applied on the o/p of test() method rather than applying it on the predicate itself (as done in Line3). If it means negating the Predicate object, then why and how is the o/p of test() method getting negated? What happens in the background that is changing the boolean value from true to false. Is it the type of predicate object returned that decides the o/p of test() method?

4) Also the o/p of Line4 is "java.util.function.Predicate$$Lambda$2/2055281021@5ca881b5" when the return type of negate() is also Predicate<T> which seems fine. Then why the o/p of isMale()/isFemale() not of the same format?

like image 837
Random Coder Avatar asked Jan 04 '23 23:01

Random Coder


1 Answers

  1. isMale() is a method that returns a Predicate<Employee>, which is a functional interface having a single method that accepts an Employee and returns a boolean.

    The method doesn't return that boolean for a given Employee. It returns a function that can be applied on any Employee and return a boolean.

  2. When you print a reference variable, you see the runtime type of the object referenced by that variable, not its compile time type (this is, of course, assuming the runtime type doesn't override toString). A lambda expression is a way to implement a functional interface. If you implemented the interface explicitly with some class Predicate<Employee> predicate1 = new ClassThatImplementsPrdicateEmployee(), printing predicate1 would give you that name of that class ClassThatImplementsPrdicateEmployee and not Predicate. Similarly, in the case of a lambda expression, the compiler generates the returned name, similar to what happens with anonymous class instances.

  3. As for what negate does, look at the default implementation :

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    

    It returns a Predicate whose implementation is the negation of applying the original Predicate's test() method on the given argument.

like image 181
Eran Avatar answered Jan 13 '23 21:01

Eran