本節是lambda表示式的一個入門課,講解的同時配有練習demo
前言什麼是lambda表示式?基礎語法函式式介面自己實現一個函式式介面jdk提供的函式式介面ConsumersupplierfunctionPredicate其他場景
前言
lambda表示式是java8推出的一個新特性。標誌著從jdk1.8開始,java正式支援函數語言程式設計。使用lambda表示式可以用簡潔流暢的程式碼完成一個功能,這也在一定程度上,可以減輕了java一直為人詬病的程式碼簡潔性問題。
什麼是lambda表示式?
lambda表示式可以簡單理解為一段可以傳遞的程式碼,核心思想是將物件導向中傳遞資料變為傳遞行為。下面舉一個編寫執行緒的例子。
1Runnable runnable = new Runnable() {
2 @Override
3 public void run() {
4 System.out.println("hello lambda");
5 }
6};
複製程式碼
這裡使用的是匿名內部類的方式。匿名內部類實現的也是將程式碼作為資料傳遞,不過使用匿名內部類還是不夠簡潔,那麼使用lambda表示式的程式碼是什麼樣的呢?
1Runnable runnable = () -> System.out.println("hello lambda");
複製程式碼
我們可以看到使用lambda表示式實現起來非常的簡單,只需要一行程式碼即可,接下來我們就試著分析一下這段程式碼。
基礎語法
我們可以將lambda表示式整體看作是一個函式,()存放的是函式的運算元 ->指向的是函式的邏輯,可以用{}包裹起來。
函式式介面
我們可以看到上述的示例程式碼,lambda表示式的引用變數是一個runnable型別,事實上,java為我們提供了多種變數型別供我們選擇,這些型別我們稱之為函式式介面。
函式式介面是隻有一個方法的介面,用作lambda表示式的型別。比如我們之前提到的Runnable介面
1@FunctionalInterface
2public interface Runnable {
3 /**
4 * When an object implementing interface <code>Runnable</code> is used
5 * to create a thread, starting the thread causes the object's
6 * <code>run</code> method to be called in that separately executing
7 * thread.
8 * <p>
9 * The general contract of the method <code>run</code> is that it may
10 * take any action whatsoever.
11 *
12 * @see java.lang.Thread#run()
13 */
14 public abstract void run();
15}
複製程式碼
我們可以看到interface上一個註解@FunctionInterface,它的作用是告訴編譯器這個介面是一個函式式介面。
自己實現一個函式式介面
我們可以自己實現一個函式式介面,判斷資料的資料是否合法
1/**
2 * 自定義函式數介面
3 *
4 * @author jialin.li
5 * @date 2020-03-18 14:22
6 */
7@FunctionalInterface
8public interface CustomFunctionInterface<T> {
9 boolean legal(T t);
10}
複製程式碼
測試方法:
1/**
2 * 測試.
3 *
4 * @author jialin.li
5 * @date 2020-03-18 14:23
6 */
7public class Test {
8
9 public boolean legal(int value, CustomFunctionInterface<Integer> functionInterface){
10 return functionInterface.legal(value);
11 }
12
13 public static void main(String[] args) {
14 System.out.println(new Test().legal(-8, (x) -> x >= 0));
15 }
16}
複製程式碼
測試結果:
1false
複製程式碼
jdk提供的函式式介面
jdk在java.util.function中為我們提供了非常豐富的函式式介面,大致可以分為4類:
接下來我們會針對這四種不同的介面,給出相應的demo,你也可以先看題目,自己嘗試寫一下
Consumer
將輸入的10進位制數,轉換為2進位制數輸出
1public void toBinaryString(int value, Consumer<Integer> consumer){
2 consumer.accept(value);
3}
4
5public static void main(String[] args) {
6 new Test().toBinaryString(15, (x) -> System.out.println(Integer.toBinaryString(x)));
7}
複製程式碼
supplier
生成n個隨機數100以內的隨機數,以陣列的形式返回
1public int[] getRandomArr(int n, Supplier<Integer> supplier) {
2 int[] arr = new int[n];
3 for (int i = 0; i < n; i++) {
4 arr[i] = supplier.get();
5 }
6 return arr;
7}
8
9public static void main(String[] args) {
10 int[] arr = new Test().getRandomArr(10, () -> new Random().nextInt(100));
11 System.out.println(Arrays.toString(arr));
12}
複製程式碼
function
生成一個[1,n]組成的階乘陣列,例如輸入3,返回[1,4,9]
1public int[] getFactorialArr(int n, Function<Integer,Integer> function) {
2 int[] arr = new int[n];
3 for (int i = 1; i <= n; i++) {
4 arr[i - 1] = function.apply(i);
5 }
6 return arr;
7}
8
9public static void main(String[] args) {
10 int[] arr = new Test().getFactorialArr(10, (x) -> x*x);
11 System.out.println(Arrays.toString(arr));
12}
複製程式碼
Predicate
判斷一個數是否是偶數
1public boolean isEven(int n, Predicate<Integer> predicate) {
2 return predicate.test(n);
3}
4
5public static void main(String[] args) {
6 boolean isEven = new Test().isEven(1102, (x) -> (x % 2 == 0));
7 System.out.println(isEven);
8}
複製程式碼
其他場景
除了上述的4個介面,java.util.function中還有許多其他的介面,可以實現各種功能。比如實現2個數的加法運算:
1public static void main(String[] args) {
2 BinaryOperator<Integer> binaryOperator = Integer::sum;
3 System.out.println(binaryOperator.apply(1, 3));
4}
複製程式碼
實現List遍歷:
1public static void main(String[] args) {
2 List<String> list = new ArrayList<>(Arrays.asList("java", "python", "go", "sql"));
3 list.forEach(System.out::println);
4}
複製程式碼
更多場景還請您去探索,感受函數語言程式設計的魅力吧
最後,期待您的訂閱和點贊,專欄每週都會更新,希望可以和您一起進步,同時也期待您的批評與指正!