Predicates Java 8的含义和用法

时间:2017-05-25 10:16:55

标签: java lambda java-8 predicate functional-interface

我正在学习功能接口,lambda表达式和谓词的概念。我可以在互联网上使用示例编写程序,但我仍然不清楚某些结构。

这是我的班级Employee,有3个数据成员,一个构造函数和相应的setter&吸气剂。

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

这是另一个有3种方法可以检查的类:

一个。员工是否是男性。 湾员工是否是女性。 C。员工的年龄是否大于通过的年龄。

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

这是我的主要课程:

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**



    }
}

我的怀疑:

1)第1行是test()接口的Predicate方法的实现吗?如果是,为什么方法isMale()的返回类型为Predicate<Employee>而不是boolean

2)第2行的o / p,即变量'predicate1'的值为“lambdaandrelated.EmployeePredicates $$Lambda $ 1 /746292446@4617c264”。但变量'predicate1'的类型为Predicate<Employee>。背景中发生了什么?

3)否定Predicate是什么意思?如果它意味着否定boolean o / p,那么它是否应该应用于test()方法的o / p而不是应用于谓词本身(如Line3中所做的那样)。如果它意味着否定Predicate对象,那么test()方法的o / p为什么以及如何被否定?在后台将boolean值从true更改为false后会发生什么。返回的谓词对象的类型是否决定了test()方法的o / p?

4)当negate()的返回类型也是Predicate<T>时,Line4的o / p也是“java.util.function.Predicate$$Lambda$2/2055281021@5ca881b5” 。那么为什么isMale() / isFemale()的o / p不是相同的格式?

3 个答案:

答案 0 :(得分:4)

  1. isMale()是一个返回Predicate<Employee>的方法,Employee是一个功能接口,只有一个方法接受boolean并返回Employee。< / p>

    该方法不会为给定的Employee返回该布尔值。它返回一个可以应用于任何toString的函数并返回一个布尔值。

  2. 当您打印引用变量时,您会看到该变量引用的对象的运行时类型,而不是其编译时类型(当然,这是假设运行时类型不会覆盖{{1} })。 lambda表达式是一种实现功能接口的方法。如果您使用某个类Predicate<Employee> predicate1 = new ClassThatImplementsPrdicateEmployee()显式实现了该接口,则打印predicate1将为您提供该类ClassThatImplementsPrdicateEmployee的名称,而不是Predicate。类似地,在lambda表达式的情况下,编译器生成返回的名称,类似于匿名类实例。

  3. 至于否定的内容,请查看默认实现:

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

    它返回Predicate,其实现是对给定参数应用原始Predicate的{​​{1}}方法的否定。

答案 1 :(得分:4)

1

你可能写得略有不同,可能会有意义:

public static Predicate<Employee> isMale() {
    return new Predicate<Employee>() {
        @Override
        public boolean test(Employee emp) {
            return emp.getGender().equalsIgnoreCase("Male");
        }
    };
}

boolean 必须是Predicate#test的返回类型。这个结构:

 return emp -> emp.getGender().equalsIgnoreCase("Male");

实际上返回一个Predicate,它有一个返回布尔值的测试方法。

2

当编译器看到lambda函数时,它将 de-sugare 指向实际编写此谓词的类中的实例方法。

所以在你的EmployeePredicates中,你会有一些像这样的方法(你可以通过javap反编译并看到它们):

private static boolean lambda$isFemale$0(Employee employee ){
    // your isFemale logic here
}

然后将为您Predicate生成一个在运行时生成的类,它将调用此方法。该类名称为:EmployeePredicates$$Lambda$1。您可以通过以下命令再次查看此类名称和代码:

  

-Djdk.internal.lambda.dumpProxyClasses = / Your / Path

所以这就是类来自的地方,名称由编译器生成。

3

基本上是!=代替Predicate的{​​{1}}。如果你看一下==的实现,这应该是明确的:

negate

应用测试,然后否定结果。

答案 2 :(得分:1)

1) 无论何时使用lambda,都要创建函数。在这种情况下,您指定该函数应为Predicate类型。由于Interface Predicate只有一种方法可以实现,因此&#39; - &gt;&#39;是该功能的实现。

2) println将调用该对象上的toString(),该对象是Predicate对象。 Lamdas将有一个toString方法的默认实现,种类可以帮助您找到它的创建位置。

3) .negate()将创建一个全新的谓词,而后者又可以进行测试。它将返回相反的值。