一、什麼是函數式編程
函數式編程是一種編程典範,它的主要思想是把計算封裝成不可變的函數,並且避免了改變狀態和共享狀態。函數式編程不僅僅是一種編程語言的特性,更是一種編程範式,其實現方式主要依靠Lambda表達式和閉包,這種方式使得代碼可讀性更高,代碼量更少。
函數式編程的主要特點如下:
- 函數是一等公民:函數可以作為參數傳遞到其他函數中,也可以作為函數的返回值。
- 純函數:一個函數的輸出結果只與輸入參數相關,不受外部環境和狀態的影響。
- 沒有副作用:函數執行時不會修改任何外部環境和狀態,只返回計算結果。
- 不可變性:函數的參數和返回值都是不可變的,在使用時需要考慮到這一點。
public class FunctionDemo {
// 傳統的方式
public static int add(int a, int b) {
return a + b;
}
// Lambda表達式
public static Function<Integer, Function<Integer, Integer>> addLambda = a -> b -> a + b;
public static void main(String[] args) {
int result1 = add(1, 2);
int result2 = addLambda.apply(1).apply(2);
System.out.println(result1);
System.out.println(result2);
}
}
二、Lambda表達式
Lambda表達式是Java8中引入的一種函數式編程的語言特性,它可以用來創建匿名函數,可以傳遞到其他函數中作為參數,使用Lambda表達式可以讓代碼更加簡潔、緊湊、易讀,且可以接受更多的函數式編程思想。
Lambda表達式由三個部分組成:一個參數列表、一個箭頭符號和一個函數體。參數列表可以是一個或多個參數,函數體可以是一條語句或一個塊,可以包含任意數量的語句。
// Lambda表達式的例子
(value) -> System.out.println(value)
// 轉換成匿名類的例子
new Consumer<Integer>() {
@Override
public void accept(Integer value) {
System.out.println(value);
}
}
Lambda表達式有以下幾種常見的形式:
- 不帶參數: () -> System.out.println(“Hello world!”)
- 帶一個參數: (str) -> System.out.println(str)
- 帶多個參數: (a, b) -> { int sum = a + b; System.out.println(sum); }
- 帶返回值: (a, b) -> a + b
- 帶參數類型: (int a, int b) -> a + b
三、方法引用
方法引用是一種更加簡潔的Lambda表達式的語法形式,它是Lambda表達式的一種語法糖。方法引用可以直接引用已有的方法或構造函數而無需創建新的Lambda表達式,可以使代碼更加簡潔、易讀。
Java8中的方法引用有四種常用的形式:
- 對象的實例方法: obj::method
- 類的靜態方法: ClassName::method
- 類的任意對象方法: ClassName::instanceMethod
- 構造函數: ClassName::new
// 方法引用的例子
stream.map(String::toUpperCase)
// 轉換成Lambda表達式的例子
stream.map(str -> str.toUpperCase())
四、Stream API
Stream API是Java8中另一個非常重要的函數式編程的特性,它可以用來處理集合對象,進行過濾、映射、排序等操作,使得代碼更加簡潔、功能更加強大。
Stream API是基於函數式編程的理念設計的,它主要包括如下幾個方面的特性:
- 惰性求值: 在流的末端操作之前,中間操作不會立即計算,只有在需要結果的時候才會計算。
- 可鏈式調用: 流的中間操作可以進行鏈式調用,方便組合各種操作。
- 函數表達式參數化: 流的操作方法接收的參數是函數式表達式,允許重寫自定義的行為。
- 並行與順序: 流中的操作可以採用並行或順序,提高效率。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// 過濾,只保留偶數
List<Integer> result1 = list.stream().filter(i -> i % 2 == 0).collect(Collectors.toList());
// 映射,將每個元素轉換成2倍
List<Integer> result2 = list.stream().map(i -> i * 2).collect(Collectors.toList());
// 排序
List<Integer> result3 = list.stream().sorted((a, b) -> b - a).collect(Collectors.toList());
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
五、Optional類型
Optional類型是Java8中引入的一種新的類型,它主要用來解決空指針異常的問題。Optional類型的主要思想是將可能為空的對象包裝成Optional對象,可避免空指針異常。
Optional類型的常用方法如下:
- of: 將一個非null的值包裝到Optional對象中。
- empty: 創建一個空的Optional對象。
- ofNullable: 將一個可以為null的值包裝到Optional對象中。
- isPresent: 判斷Optional對象是否存在非null的值。
- orElse: 如果Optional對象持有非null的值,則返回該值,否則返回orElse方法中的參數。
- orElseGet: 如果Optional對象持有非null的值,則返回該值,否則調用orElseGet方法中的Supplier函數式介面。
Optional<String> optional1 = Optional.of("Hello");
Optional<String> optional2 = Optional.empty();
// get方法獲取值
System.out.println(optional1.get());
// orElse方法獲取值
System.out.println(optional1.orElse("world"));
System.out.println(optional2.orElse("world"));
// orElseGet方法獲取值
System.out.println(optional1.orElseGet(() -> "world"));
System.out.println(optional2.orElseGet(() -> "world"));
六、總結
Java8中的函數式編程提供了一種新的方式來編寫Java程序,它使得代碼更加簡潔、易讀,功能更加強大,同時也幫助我們避免了很多錯誤和陷阱。函數式編程是一種新的編程範式,它的思想已經被越來越多的編程語言所採納,它將會是未來編程的一個趨勢。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/239878.html