1. 程式人生 > >Java lambda表達式

Java lambda表達式

action 需要 一次 println 自動 cat 表示 規則 例子

lambda表達式是一個匿名函數,通俗解釋是:可以傳遞的、在以後執行一次或多次的代碼塊。Java8中引入的特性。

lambda表達式的語法

形式:(參數)-> 表達式

0.若表達式復雜,可以用大括號括起。{語句塊}

1.沒有參數的情況:仍然需要提供空括號。

()->{for (int i = 100;i >= 0;i--) System.out.println(i);}

2.如果可以推導出參數類型:可以忽略參數類型。

Compertor<String> comp = (first,second) ->first.length()-scond.length();//參數類型必為字符串

3.如果只有一個參數,可以推導出參數類型:可以省略小括號。

4.無需指定lambda表達式的返回類型,自動由上下文推導得出。

函數式接口

對於只有一個抽象方法的接口,需要這種接口的對象時,可以提供一個lambda表達式。只有一個抽象方法的接口被稱為函數式接口。

如Array.sort方法需要提供一個數組和比較器(comparator)。比較器是實現了Comparator接口的實例對象。該接口只有一個方法。如普通實現:

class LengthComparater implements Comparator<String>{
    public int compare(String first,String second){
        
return first.length() - second.length(); } }

這樣,就可以創建一個LengthComparater類傳入Array.sort函數中。

Array.sort(words,new LengthComparator())

而用lambda表達式:

Array.sort(words,(first,second)->first.length()-secong.length())

這樣做,對compare方法的調用會執行這個lambda表達式的體,它把lambda看做一個函數。這樣做法效率要高;代碼可讀性也要好一些。

方法引用

使用雙冒號(::)分隔方法和對象名來表示一個方法引用

,與lambda表達式效果相同。有3種寫法:

object::instanceMethod(x,x,x...)   等價於(x,x,x...)->object.instanceMethod(x,x,x...)

Class::staticMethod(x,x,x,....) 等價於(x,x,x...)->object.staticMethod(x,x,x...)

Class::instanceMethod(x,y,z...) 等價於(x)->x.instanceMethod(y,z.....)  //第一個參數會成為方法的目標

可以在方法引用中使用this和super參數

構造器引用

與方法引用類似,方法名為new。例如Person::new是Person構造器的一個引用。

變量作用域

lambda表達式可以捕獲外圍作用域中變量的值,但卻有些限制。

規則:lambda表達式中捕獲的變量必須實際上是最終變量。

一個例子:

    public static void repeat(String text, int count){
        for (int i = 1;i <= count; i++){
            ActionListener ls = event ->{
                System.out.println(i + " " + text);
            };
            new Timer(10000,ls).start();
        }
    }

如上,對於text的打印是合法的,對i的打印卻是非法的。text總是指向同一個對象;而i的值卻會改變。

規則:lambda表達式的體與嵌套塊有相同的作用域。

一個例子:

    Path first = Paths.get("usr/bin");
    Comparator<String> comb = (first,second) -> first.length()-second.length();

以上是非法的。方法中不能有兩個同名的局部變量。所以以上lambda表達式不能使用first變量名作為參數。

處理lambda表達式

簡單例子:重復一個動作n次,用到repeat方法。

repeat(10,()->(System.out.println("hello world"));

需要實現一個函數式接口,這裏使用Runnable接口,調用action.run()時會執行這個函數主體:

public static void repeat(int n,Runnable action){
    for(int i;i<n;i++) action.run();
}

實際上lambda表達式能做的也就是轉換成函數式接口。

一些常用的函數式接口:Runnable,Supplier,Consumer,BiConsumer,Function,BiFunction,UnaryOperator,BinaryOperator,Predicate,BiPredicate。

Java lambda表達式