lambda表示數學符號「λ」,計算機領域中λ表明「λ演算」,表達了計算機中最基本的概念:「調用」和「置換」。html
全局model代碼:Employee.javajava
package www.muzi.com.model; /** * Date:2017/3/3 12:44 */ public class Employee { private String name; private int age; public Employee() { } public Employee(String name, int age) { this.name = name; this.age = age; } public Employee(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Java8中引入了一個新的操做符"->",該操做符稱做箭頭操做符或者Lambda操做符,箭頭操做符將Lambda表達式拆分爲兩部分:編程
左側:Lambda 表達式參數列表
右側:Lambda 表達式中須要執行的功能,及Lambda體api
public void repeatMessage(String content, int count) { Runnable r = () -> { for (int i = 0; i < count; i++) { System.out.println(i + "-" + content); count++;//錯誤,不能更改已捕獲變量的值 } }; r.run(); } @Test public void test8() { repeatMessage("測試", 10); }
@Test public void test9(){ //嵌套臺代碼塊 String ss = ""; { String ss="dd"; } //Lambda Comparator<String> com = (ss, yy) -> Integer.compare(ss.length(), yy.length()); System.out.println(ss); }
語法格式一:無參數,無返回值 () -> System.out.println("Hello Lambda");數組
@Test public void test1(){ int num = 0; //jdk1.7以前,必須是final的 Runnable r = new Runnable() { @Override public void run() { System.out.println("Hello World!" + num); } }; r.run(); System.out.println("------------------"); Runnable r1 = () -> System.out.println("Hello Lambda!" + num); r1.run(); }
語法格式二:有一個參數,無返回值 (x) -> System.out.println(x);閉包
語法格式三:當只有一個參數時,小括號能夠省略不寫 x -> System.out.println(x);oracle
@Test public void test2(){ Consumer<String> con = (x) -> System.out.println(x); Consumer<String> con1 = x -> System.out.println(x); con.accept("測試Lambda表達式!"); }
語法格式四:當有兩個或以上參數時,有返回值,而且Lambda中有多條語句
(x, y) -> {
System.out.println("函數式接口");
return Integer.compare(x, y);
};app
@Test public void test3(){ Comparator<Integer> com = (x, y) -> { System.out.println("函數式接口"); return Integer.compare(x, y); }; System.out.println(com.compare(2, 3)); }
語法格式五:當有兩個或以上參數時,有返回值,Lambda中有一條語句,大括號和return能夠省略不寫dom
(x, y) -> Integer.compare(x, y);ide
@Test public void test4(){ Comparator<Integer> com = (x, y) -> Integer.compare(x, y); System.out.println(com.compare(2, 3)); }
語法格式六:Lambda參數列表的數據類型能夠省略不寫,由於JVM編譯器能夠經過上下文推斷出,數據類型,即「類型推斷」
(Integer x, Integer y) -> Integer.compare(x, y);
@Test public void test5(){ Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y); System.out.println(com.compare(2, 3)); //類型推斷舉例 List<String> list = new ArrayList<>();//jdk1.7中new ArrayList<String>()必須帶類型,1.8版本不須要帶類型 }
函數式接口:接口中只有一個抽象方法的接口,成爲函數式接口。
可使用註解@FunctionalInterface修飾,能夠檢查是不是函數式接口。
函數式接口源代碼:
package www.muzi.com; /** * Date:2017/3/6 18:02 */ @FunctionalInterface public interface MyFun<T> { public Integer getValue(Integer num); }
//需求:對一個數進行運算 @Test public void test6(){ Integer num = operation(100, x -> x * x); System.out.println("num = " + num); Integer num1 = operation(200, y -> y + 200); System.out.println("num1 = " + num1); } public Integer operation(Integer num, MyFun<Integer> mf){ return mf.getValue(num); }
由於目前在寫Lambda表達式時,老是須要去寫一個函數式接口。這樣其實也挺繁瑣,其實Java8已經替咱們內置了許多函數式接口,接下來介紹Java8內置四大函數式接口。
在Java8中添加了許多內置的函數式接口:
這裏就展現如下四中函數式接口,其餘函數式接口看java8文檔:
http://docs.oracle.com/javase/8/docs/api/index.html
//Consumer<T> : 消費型接口 @Test public void test1(){ happy(10000, m -> System.out.println("訂餐消費" + m + "元")); } public void happy(double money, Consumer<Double> con){ con.accept(money); };
//Supplier<T> : 供給型接口 @Test public void test2(){ List<Integer> numList = getNumberList(10, () -> (int)(Math.random() * 100)); for (Integer n : numList) { System.out.println(n); } } //需求:產生指定個數的整數,並放到集合中 public List<Integer> getNumberList(int num, Supplier<Integer> sup){ List<Integer> list = new ArrayList<>(); for (int i = 0; i < num; i++) { Integer n = sup.get(); list.add(n); } return list; };
//Function<T, R> : 函數型接口 @Test public void test3(){ String str = strHandler("測試函數式接口 ", x -> x.trim()); System.out.println(str + "--"); } //需求:處理字符串 public String strHandler(String str, Function<String, String> fun){ return fun.apply(str); }
方法引用:若 Lambda 體中的功能,已經有方法提供了實現,可使用方法引用(能夠將方法引用理解爲 Lambda 表達式的另一種表現形式)。
::操做符將方法名和對象或類的名字分隔開來,主要介紹常使用的三種方法引用方式。
//對象的引用 :: 實例方法名 @Test public void test1(){ Consumer<Integer> con = (x) -> System.out.println(x); //使用方法引用實現 PrintStream ps = System.out; Consumer<Integer> con1 = ps::println; Consumer<Integer> con2 = System.out::println; con2.accept(1234); } @Test public void test2(){ Employee employee = new Employee("木子",23); Supplier<String> sup = employee:: getName; String name = sup.get(); System.out.println(name); }
//類名 :: 靜態方法名 @Test public void test3(){ Comparator<Integer> com = (x, y) -> Integer.compare(x, y); //方法引用 //方法引用所引用的方法的參數列表與返回值類型,須要與函數式接口中抽象方法的參數列表和返回值類型保持一致! Comparator<Integer> com1 = Integer:: compare; int result = com1.compare(3, 5); System.out.println(result); }
//類名 :: 實例方法名 @Test public void test4(){ BiPredicate<String, String> bp = (x, y) -> x.equals(y); //若Lambda 的參數列表的第一個參數,是實例方法的調用者,第二個參數(或無參)是實例方法的參數時,格式: ClassName::MethodName BiPredicate<String, String> bp1 = String:: equals; boolean result = bp1.test("as", "as"); System.out.println(result); }
注意:
①方法引用所引用的方法的參數列表與返回值類型,須要與函數式接口中抽象方法的參數列表和返回值類型保持一致!
②若Lambda 的參數列表的第一個參數,是實例方法的調用者,第二個參數(或無參)是實例方法的參數時,格式: ClassName::MethodName
格式: ClassName :: new
//構造器引用 @Test public void test5(){ Supplier<Employee> sup = () -> new Employee(); //構造器引用,自動匹配對應的構造器 Supplier<Employee> sup1 = Employee::new;//由於沒有傳參數,這裏的new引用的是無參構造器 Employee employee = sup1.get(); System.out.println(employee); //Employee{name='null', age=0} } @Test public void test6(){ Function<String, Employee> fun = (x) -> new Employee(x); Function<String, Employee> fun1 = Employee::new;//這裏引用的是一個參數的構造器 System.out.println(fun1.apply("haha"));//Employee{name='haha', age=0} }
構造器引用 : 構造器的參數列表,須要與函數式接口中參數列表保持一致!
格式: Type :: new
//數組引用 @Test public void test7(){ Function<Integer, String[]> fun = (x) -> new String[x]; String[] strs = fun.apply(10); System.out.println(strs.length); //10 Function<Integer, String[]> fun1 = String[]::new; String[] strs1 = fun.apply(15); System.out.println(strs1.length); //15 }