歡迎您光臨本站 註冊首頁

Java Predicate及Consumer接口函數代碼實現解析

←手機掃碼閱讀     qp18502452 @ 2020-06-11 , reply:0

Predicate函數編程
 

Predicate功能判斷輸入的對象是否符合某個條件。官方文檔解釋到:Determines if the input object matches some criteria.

瞭解Predicate接口作用後,在學習Predicate函數編程前,先看一下Java 8關於Predicate的源碼:

  @FunctionalInterface  public interface Predicate{      /**     * Evaluates this predicate on the given argument.     *     * @param t the input argument     * @return {@code true} if the input argument matches the predicate,     * otherwise {@code false}     */    boolean test(T t);      default Predicateand(Predicate other) {      Objects.requireNonNull(other);      return (t) -> test(t) && other.test(t);    }      default Predicatenegate() {      return (t) -> !test(t);    }      default Predicateor(Predicate other) {      Objects.requireNonNull(other);      return (t) -> test(t) || other.test(t);    }        staticPredicateisEqual(Object targetRef) {      return (null == targetRef)          ? Objects::isNull          : object -> targetRef.equals(object);    }  }

 

從上面代碼可以發現,Java 8新增了接口的默認(default)方法和(static)靜態方法。在Java 8以前,接口裡的方法要求全部是抽象方法。但是靜態(static)方法只能通過接口名調用,不可以通過實現類的類名或者實現類的對象調用;默認(default)方法只能通過接口實現類的對象來調用。

接下來主要來使用接口方法test,可以使用匿名內部類提供test()方法的實現,也可以使用lambda表達式實現test()。
 體驗一下Predicate的函數式編程,使用lambda實現。其測試代碼如下:

  @Test  public void testPredicate(){    java.util.function.PredicateboolValue = x -> x > 5;    System.out.println(boolValue.test(1));//false    System.out.println(boolValue.test(6));//true  }

 

第1行代碼:定義一個Predicate實現,入參為Integer,返回傳入參數與5做比較。
 第2,3行代碼調用第一行,傳入相關參數。

Consumer函數編程
 

Consumer接口的文檔聲明如下:

An operation which accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects.

即接口表示一個接受單個輸入參數並且沒有返回值的操作。不像其它函數式接口,Consumer接口期望執行帶有副作用的操作(Consumer的操作可能會更改輸入參數的內部狀態)。

同樣,在瞭解Consumer函數編程前,看一下Consumer源代碼,其源代碼如下:

  @FunctionalInterface  public interface Consumer{      /**     * Performs this operation on the given argument.     *     * @param t the input argument     */    void accept(T t);      /**     * Returns a composed {@code Consumer} that performs, in sequence, this     * operation followed by the {@code after} operation. If performing either     * operation throws an exception, it is relayed to the caller of the     * composed operation. If performing this operation throws an exception,     * the {@code after} operation will not be performed.     *     * @param after the operation to perform after this operation     * @return a composed {@code Consumer} that performs in sequence this     * operation followed by the {@code after} operation     * @throws NullPointerException if {@code after} is null     */    default ConsumerandThen(Consumer after) {      Objects.requireNonNull(after);      return (T t) -> { accept(t); after.accept(t); };    }  }

 

從上面代碼可以看出,Consumer使用了Java 8接口新特性――接口默認(default)方法。接下來使用接口方法accept,體驗一下Consumer函數編程。其測試代碼如下:

  @Test  public void testConsumer(){    User user = new User("zm");    //接受一個參數    ConsumeruserConsumer = User1 -> User1.setName("zmChange");    userConsumer.accept(user);    System.out.println(user.getName());//zmChange  }

 

在Java 8之前的實現如下:

  @Test  public void test(){    User user = new User("zm");    this.change(user);    System.out.println(user.getName());//輸出zmChange  }    private void change(User user){    user.setName("zmChange");  }

 

Predicate和Consumer綜合應用
 

為了詳細說明Predicate和Consumer接口,通過一個學生例子:Student類包含姓名、分數以及待付費用,每個學生可根據分數獲得不同程度的費用折扣。

Student類源代碼:

  public class Student {      String firstName;      String lastName;      Double grade;      Double feeDiscount = 0.0;    Double baseFee = 2000.0;    public Student(String firstName, String lastName, Double grade) {      this.firstName = firstName;      this.lastName = lastName;      this.grade = grade;    }      public void printFee(){      Double newFee = baseFee - ((baseFee * feeDiscount)/100);      System.out.println("The fee after discount: " + newFee);    }  }

 

然後分別聲明一個接受Student對象的Predicate接口以及Consumer接口的實現類。本例子使用Predicate接口實現類的test()方法判斷輸入的Student對象是否擁有費用打折的資格,然後使用Consumer接口的實現類更新輸入的Student對象的折扣。

  public class PredicateConsumerDemo {      public static Student updateStudentFee(Student student, Predicatepredicate, Consumerconsumer){      if (predicate.test(student)){        consumer.accept(student);      }      return student;    }    }

 

Predicate和Consumer接口的test()和accept()方法都接受一個泛型參數。不同的是test()方法進行某些邏輯判斷並返回一個boolean值,而accept()接受並改變某個對象的內部值。updateStudentFee方法的調用如下所示:

  public class Test {    public static void main(String[] args) {      Student student1 = new Student("Ashok","Kumar", 9.5);        student1 = updateStudentFee(student1,          //Lambda expression for Predicate interface          student -> student.grade > 8.5,          //Lambda expression for Consumer inerface          student -> student.feeDiscount = 30.0);      student1.printFee(); //The fee after discount: 1400.0        Student student2 = new Student("Rajat","Verma", 8.0);      student2 = updateStudentFee(student2,          //Lambda expression for Predicate interface          student -> student.grade >= 8,          //Lambda expression for Consumer inerface          student -> student.feeDiscount = 20.0);      student2.printFee();//The fee after discount: 1600.0      }  }

 

通過簡單對Predicate接口和Consumer接口進行應用,對函數式編程有了一個直觀認識。


[qp18502452 ] Java Predicate及Consumer接口函數代碼實現解析已經有233次圍觀

http://coctec.com/docs/java/show-post-238073.html