Java的函數(shù)式接口編程示例

背景
函數(shù)式接口是在Java 8中引入的,與Lambda表達式和方法引用一起。這三個特性被添加到Java中,以促進函數(shù)式編程并編寫干凈、可讀的代碼。在Java 8之前,需要編寫大量樣板代碼來涵蓋基本功能。例如,為了調(diào)用一個函數(shù),首先我們必須創(chuàng)建一個具有所需方法的類,創(chuàng)建類的實例,然后使用實例來調(diào)用方法,或者使用具有相應(yīng)方法的匿名類的另一種方式。
使用Lambda表達式,我們可以避免使用具體類和匿名類對象的需求。函數(shù)式接口更進一步,因為Lambda表達式只需要實現(xiàn)一個方法,所以可以輕松地實現(xiàn)函數(shù)式接口。
函數(shù)式接口只展示一個功能。例如,一個具有單一方法compareTo()的Comparable接口用于比較目的。但它可以有任意數(shù)量的默認(rèn)方法和靜態(tài)方法。
Java 8定義了許多函數(shù)式接口,可以廣泛用于Lambda表達式。以下是在java.util.Function包中定義的函數(shù)式接口列表。
@FunctionalInterface注解,按照功能,任何具有單個抽象方法的接口都是函數(shù)式接口。Java提供了@FunctionalInterface注解,以將一個接口標(biāo)記為函數(shù)式接口,以便編譯器可以檢查接口是否是函數(shù)式接口。此注解是可選的,主要是為了增加編譯器的檢查和增加代碼的可讀性和維護性。
函數(shù)式接口編程示例
函數(shù)式接口的類型:在Java中,主要有四種類型的函數(shù)式接口。
Predicate函數(shù)式接口:Predicate函數(shù)式接口是一種方法接受一個參數(shù),并返回true或false的接口。Predicate函數(shù)式接口主要用于比較元素以進行排序或根據(jù)應(yīng)用于傳入的輸入的某些條件來過濾值。Java提供了用于基本類型的Predicate函數(shù)式接口,如IntPredicate、DoublePredicate和LongPredicate,分別只接受Integer、Double和Long類型的參數(shù)。
用法:
Predicate predicate = (value) -> value != 0; //或者
Predicate predicate = (value) -> test(value);在上面的代碼片段中,predicate函數(shù)根據(jù)傳入的值返回true或false。
示例:
在這個例子中,我們使用predicate函數(shù)式接口和lambda表達式來從一個整數(shù)列表中過濾出奇數(shù)。
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);
   }
}編譯運行上述程序后,輸出結(jié)果為:
[2, 4, 6, 8]Consumer函數(shù)式接口:Consumer函數(shù)式接口是一種方法接受一個參數(shù),并且不返回任何值的接口。Consumer函數(shù)式接口主要用于執(zhí)行副作用操作。例如,打印一個元素、添加稱謂等。還有其他變種的Consumer,比如BiConsumer。BiConsumer函數(shù)式接口可以接受兩個參數(shù)。Java提供了用于基本類型的Consumer函數(shù)式接口,如IntConsumer、DoubleConsumer和LongConsumer,分別只接受Integer、Double和Long類型的參數(shù)。
用法:
//定義
Consumer consumer = (value) -> System.out.println(value);
// 或者
Consumer consumer1 = System.out::println;
// 使用
Consumer consumer2 = (value) -> accept(value);示例:
在這個例子中,我們借助lambda表達式和方法引用,使用consumer函數(shù)式接口來打印整數(shù)列表中的所有數(shù)字。
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);
   }
}編譯運行程序結(jié)果如下:
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
8Supplier函數(shù)式接口:Supplier函數(shù)式接口是一種沒有任何參數(shù)傳遞且會返回一個值的接口。Supplier函數(shù)式接口主要用于延遲生成值。例如,獲取一個隨機數(shù),生成一系列數(shù)字等。
用法:
//定義
Supplier supplier = () -> Math.random() * 10;
// 使用
Supplier supplier1 = () -> get();示例:
在這個例子中,我們借助lambda表達式,使用Supplier函數(shù)式接口來獲取一個隨機數(shù)。
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);
   }
}編譯并運行程序,得出運行結(jié)果:
[0, 8, 8, 8, 8, 5, 7, 5, 5, 9]Function函數(shù)式接口:Function函數(shù)式接口是一種方法接受一個參數(shù)并返回一個值的接口。Function函數(shù)式接口主要用于獲取處理后的值。例如,獲取一個元素的平方,修剪字符串值等。還有其他的Function變體,比如BiFunction。BiFunction函數(shù)式接口可以接受兩個參數(shù)。Java還提供了針對基本類型的Function函數(shù)式接口,如IntFunction、DoubleFunction和LongFunction,分別只接受Integer、Double和Long類型的參數(shù)。還有兩個更實用的接口,UnaryOperator擴展了Function接口,BinaryOperator擴展了BiFunction接口。
用法:
//定義
Function function = (value) -> Math.random() * 10;
// 使用
Function function1 = (value) -> apply(value);示例:
在這個例子中,我們借助lambda表達式,使用Function函數(shù)式接口來獲取一個平方數(shù)。
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);
   }
}編譯并運行程序,得出運行結(jié)果:
[1, 4, 9, 16, 25, 36, 49, 64]注意事項:
在Java 8之前,已經(jīng)存在的許多接口被注釋為函數(shù)式接口,并可以在lambda表達式中使用。例如:
- Runnable ?提供run() 方法
 - Callable ? 提供 call() 方法
 - Actionlistener ? 提供actionPerformed() 方法
 - Comparable ? 提供 compareTo() 方法比較兩個數(shù)的大小
 
示例:
在這個例子中,我們創(chuàng)建了兩個線程。第一個線程使用匿名類創(chuàng)建,第二個線程使用lambda表達式創(chuàng)建。兩者都使用runnable接口來創(chuàng)建線程實例。
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();   
   }
}編譯并運行程序,結(jié)果:
Thread 1 is running
Thread 2 is running.














 
 
 






 
 
 
 