Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤與異常

Java 多執行緒

Java 同步

Java 網路程式設計

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 其他

Java APIs 與框架

Java 類引用

Java 有用資源

Java - 函式式介面



**函式式介面**是在 Java 8 中與lambda 表示式方法引用一起引入的。這三個特性是為了增強Java中的函數語言程式設計,並編寫簡潔易讀的程式碼。在 Java 8 之前,需要編寫大量樣板程式碼來實現基本功能。例如,為了呼叫一個函式,首先必須建立一個包含所需方法的類,建立一個類例項,然後使用該例項來呼叫方法,或者使用匿名類及其相應的方法。

使用 lambda 表示式,我們可以避免對具體類和匿名類物件的需要。**函式式介面**更進一步,因為 lambda 表示式可以很容易地實現函式式介面,因為它只需要實現一個方法。

**函式式介面**只有一個功能。例如,具有單個方法 compareTo() 的 Comparable 介面用於比較目的。但它可以有任意數量的預設方法和靜態方法。

Java 8 定義了許多函式式介面,這些介面廣泛用於 lambda 表示式中。以下是 java.util.Function 包中定義的函式式介面列表。

@FunctionalInterface 註解

從功能上講,任何只有一個抽象方法的介面都是函式式介面。Java 提供了一個 @FunctionalInterface 註解,用於將介面標記為函式式介面,以便編譯器可以檢查介面是否為函式式介面。此註解是可選的,主要用於新增編譯器檢查,並提高程式碼的可讀性和可維護性。

Java 中函式式介面的型別

Java 中主要有四種類型的函式式介面。

Predicate 函式式介面

謂詞函式式介面是一種其方法接受一個引數並返回 true 或 false 的介面。謂詞函式式介面主要用於比較排序元素或根據應用於傳遞輸入的某些條件過濾值。Java 還為基本型別提供了謂詞函式式介面,例如 IntPredicate、DoublePredicate 和 LongPredicate,它們分別只接受 Integer、Double 和 Long。

用法

Predicate predicate = (value) -> value  != 0;
// or
Predicate predicate = (value) -> test(value);

在上面的程式碼片段中,謂詞函式根據傳遞的值返回 true/false。

示例

在這個例子中,我們使用謂詞函式式介面來過濾整數列表中的奇數,藉助 lambda 表示式。

package com.tutorialspoint;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Tester {
   public static void main(String args[]) {
      List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8);

      Predicate<Integer> isEvenNumber = n -> n %2 == 0;
      numbers =  numbers.stream().filter(isEvenNumber).toList();

      System.out.println(numbers);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

[2, 4, 6, 8]

Consumer 函式式介面

Consumer 函式式介面是一種其方法接受一個引數但不返回值的介面。Consumer 函式式介面主要用於副作用操作。例如,列印元素,新增問候語等。Consumer 也有其他變體,如 BiConsumer。BiConsumer 函式式介面可以接受兩個引數。Java 還為基本型別提供了 consumer 函式式介面,例如 IntConsumer、DoubleConsumer 和 LongConsumer,它們分別只接受 Integer、Double 和 Long。

用法

Consumer consumer = (value) -> System.out.println(value);
// Or
Consumer consumer1 = System.out::println;
// Or
Consumer consumer2 = (value) -> accept(value);

示例

在這個例子中,我們使用 consumer 函式式介面來列印整數列表中的所有數字,藉助 lambda 表示式和方法引用。

package com.tutorialspoint;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Tester {
   public static void main(String args[]) {
      List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8);

      Consumer<Integer> consumer = (value) -> System.out.println(value);
      Consumer consumer1 = System.out::println;

      System.out.println("Printing using consumer functional interface as lambda expression");
      numbers.forEach(consumer);

      System.out.println("Printing using consumer functional interface as method reference");
      numbers.forEach(consumer1);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

Printing using consumer functional interface as lambda expression
1
2
3
4
5
6
7
8
Printing using consumer functional interface as method reference
1
2
3
4
5
6
7
8

Supplier 函式式介面

Supplier 函式式介面是一種其方法沒有任何引數並返回值的介面。Supplier 函式式介面主要用於延遲生成值。例如,獲取隨機數,生成數字序列等。

用法

Supplier supplier = () -> Math.random() * 10;
// or
Supplier supplier1 = () -> get();

示例

在這個例子中,我們使用 Supplier 函式式介面來獲取隨機數,藉助 lambda 表示式。

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public class Tester {
   public static void main(String args[]) {
      Supplier<Integer> supplier = () -> (int)(Math.random() * 10);

      List<Integer> randomNumbers = new ArrayList<>();

      // generate 10 random numbers
      for(int i = 0; i< 10; i++) {
         randomNumbers.add(supplier.get());
      }
      System.out.println(randomNumbers);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

[0, 8, 8, 8, 8, 5, 7, 5, 5, 9]

Function 函式式介面

函式式介面是指其方法接受一個引數並返回一個值的方法。函式式介面主要用於獲取處理後的值。例如,獲取元素的平方、修剪字串值等。Function還有其他變體,例如BiFunction。BiFunction函式式介面可以接受兩個引數。Java也為基本資料型別提供了函式式介面,例如IntFunction、DoubleFunction和LongFunction,它們分別只接受Integer、Double和Long。還有兩個實用程式介面,UnaryOperator擴充套件了Function介面,BinaryOperator擴充套件了BiFunction介面。

用法

Function function = (value) -> Math.random() * 10;
// or
Function function1 = (value) -> apply(value);

示例

在這個例子中,我們使用函式式介面和lambda表示式來獲取數字平方的列表。

package com.tutorialspoint;

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class Tester {
   public static void main(String args[]) {
      List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8);

      Function<Integer, Integer> squared = (value) -> value * value;  

      List<Integer> squaredNumbers =  numbers.stream().map(squared).toList();

      System.out.println(squaredNumbers);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

[1, 4, 9, 16, 25, 36, 49, 64]

Java 8之前已存在的函式式介面

在Java中,許多現有的介面都被註釋為函式式介面,並且可以在lambda表示式中使用。例如:

  • Runnable − 提供run()方法

  • Callable − 提供call()方法

  • ActionListener − 提供actionPerformed()方法

  • Comparable − 提供compareTo()方法來比較兩個數字

示例

在這個例子中,我們建立了兩個執行緒。第一個使用匿名類建立,第二個使用lambda表示式建立。兩者都使用Runnable介面來建立執行緒例項。

package com.tutorialspoint;

public class Tester {
   public static void main(String args[]) {
      // create anonymous inner class object
      new Thread(new Runnable() {
         @Override public void run() {
            System.out.println("Thread 1 is running");
         }
      }).start();

      // lambda expression to create the object
      new Thread(() -> {
         System.out.println("Thread 2 is running.");
      }).start();   
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

Thread 1 is running
Thread 2 is running.
廣告