1.
/** * Lambda表達式的使用舉例 * */ public class LambdaTest { @Test public void test1(){ Runnable r1 = new Runnable() { @Override public void run() { System.out.println("我愛北京天安門"); } }; r1.run(); System.out.println("***********************"); Runnable r2 = () -> System.out.println("我愛北京故宮"); r2.run(); } @Test public void test2(){ Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return Integer.compare(o1,o2); } }; int compare1 = com1.compare(12,21); System.out.println(compare1); System.out.println("***********************"); //Lambda表達式的寫法 Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2); int compare2 = com2.compare(32,21); System.out.println(compare2); System.out.println("***********************"); //方法引用 Comparator<Integer> com3 = Integer :: compare; int compare3 = com3.compare(32,21); System.out.println(compare3); } }
2.
/** * Lambda表達式的使用 * * 1.舉例: (o1,o2) -> Integer.compare(o1,o2); * 2.格式: * -> :lambda操作符 或 箭頭操作符 * ->左邊:lambda形參列表 (其實就是接口中的抽象方法的形參列表) * ->右邊:lambda體 (其實就是重寫的抽象方法的方法體) * * 3. Lambda表達式的使用:(分爲6種情況介紹) * * 總結: * ->左邊:lambda形參列表的參數類型可以省略(類型推斷);如果lambda形參列表只有一個參數,其一對()也可以省略 * ->右邊:lambda體應該使用一對{}包裹;如果lambda體只有一條執行語句(可能是return語句),省略這一對{}和return關鍵字 * * 4.Lambda表達式的本質:作爲函數式接口的實例 * * 5. 如果一個接口中,只聲明瞭一個抽象方法,則此接口就稱爲函數式接口。我們可以在一個接口上使用 @FunctionalInterface 註解, * 這樣做可以檢查它是否是一個函數式接口。 * * 6. 所以以前用匿名實現類表示的現在都可以用Lambda表達式來寫。 */ public class LambdaTest1 { //語法格式一:無參,無返回值 @Test public void test1(){ Runnable r1 = new Runnable() { @Override public void run() { System.out.println("我愛北京天安門"); } }; r1.run(); System.out.println("***********************"); Runnable r2 = () -> { System.out.println("我愛北京故宮"); }; r2.run(); } //語法格式二:Lambda 需要一個參數,但是沒有返回值。 @Test public void test2(){ Consumer<String> con = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }; con.accept("謊言和誓言的區別是什麼?"); System.out.println("*******************"); Consumer<String> con1 = (String s) -> { System.out.println(s); }; con1.accept("一個是聽得人當真了,一個是說的人當真了"); } //語法格式三:數據類型可以省略,因爲可由編譯器推斷得出,稱爲“類型推斷” @Test public void test3(){ Consumer<String> con1 = (String s) -> { System.out.println(s); }; con1.accept("一個是聽得人當真了,一個是說的人當真了"); System.out.println("*******************"); Consumer<String> con2 = (s) -> { System.out.println(s); }; con2.accept("一個是聽得人當真了,一個是說的人當真了"); } @Test public void test4(){ ArrayList<String> list = new ArrayList<>();//類型推斷 int[] arr = {1,2,3};//類型推斷 } //語法格式四:Lambda 若只需要一個參數時,參數的小括號可以省略 @Test public void test5(){ Consumer<String> con1 = (s) -> { System.out.println(s); }; con1.accept("一個是聽得人當真了,一個是說的人當真了"); System.out.println("*******************"); Consumer<String> con2 = s -> { System.out.println(s); }; con2.accept("一個是聽得人當真了,一個是說的人當真了"); } //語法格式五:Lambda 需要兩個或以上的參數,多條執行語句,並且可以有返回值 @Test public void test6(){ Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); } }; System.out.println(com1.compare(12,21)); System.out.println("*****************************"); Comparator<Integer> com2 = (o1,o2) -> { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); }; System.out.println(com2.compare(12,6)); } //語法格式六:當 Lambda 體只有一條語句時,return 與大括號若有,都可以省略 @Test public void test7(){ Comparator<Integer> com1 = (o1,o2) -> { return o1.compareTo(o2); }; System.out.println(com1.compare(12,6)); System.out.println("*****************************"); Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2); System.out.println(com2.compare(12,21)); } @Test public void test8(){ Consumer<String> con1 = s -> { System.out.println(s); }; con1.accept("一個是聽得人當真了,一個是說的人當真了"); System.out.println("*****************************"); Consumer<String> con2 = s -> System.out.println(s); con2.accept("一個是聽得人當真了,一個是說的人當真了"); } }
3.
/** * java內置的4大核心函數式接口 * * 消費型接口 Consumer<T> void accept(T t) * 供給型接口 Supplier<T> T get() * 函數型接口 Function<T,R> R apply(T t) * 斷定型接口 Predicate<T> boolean test(T t) * */ public class LambdaTest2 { @Test public void test1(){ happyTime(500, new Consumer<Double>() { @Override public void accept(Double aDouble) { System.out.println("學習太累了,去天上人間買了瓶礦泉水,價格爲:" + aDouble); } }); System.out.println("********************"); happyTime(400,money -> System.out.println("學習太累了,去天上人間喝了口水,價格爲:" + money)); } public void happyTime(double money, Consumer<Double> con){ con.accept(money); } @Test public void test2(){ List<String> list = Arrays.asList("北京","南京","天津","東京","西京","普京"); List<String> filterStrs = filterString(list, new Predicate<String>() { @Override public boolean test(String s) { return s.contains("京"); } }); System.out.println(filterStrs); List<String> filterStrs1 = filterString(list,s -> s.contains("京")); System.out.println(filterStrs1); } //根據給定的規則,過濾集合中的字符串。此規則由Predicate的方法決定 public List<String> filterString(List<String> list, Predicate<String> pre){ ArrayList<String> filterList = new ArrayList<>(); for(String s : list){ if(pre.test(s)){ filterList.add(s); } } return filterList; } }
4.
public class Employee { private int id; private String name; private int age; private double salary; public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public Employee() { System.out.println("Employee()....."); } public Employee(int id) { this.id = id; System.out.println("Employee(int id)....."); } public Employee(int id, String name) { this.id = id; this.name = name; } public Employee(int id, String name, int age, double salary) { this.id = id; this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Employee employee = (Employee) o; if (id != employee.id) return false; if (age != employee.age) return false; if (Double.compare(employee.salary, salary) != 0) return false; return name != null ? name.equals(employee.name) : employee.name == null; } @Override public int hashCode() { int result; long temp; result = id; result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + age; temp = Double.doubleToLongBits(salary); result = 31 * result + (int) (temp ^ (temp >>> 32)); return result; } }
5.
/** * 提供用於測試的數據 */ public class EmployeeData { public static List<Employee> getEmployees(){ List<Employee> list = new ArrayList<>(); list.add(new Employee(1001, "馬化騰", 34, 6000.38)); list.add(new Employee(1002, "馬雲", 12, 9876.12)); list.add(new Employee(1003, "劉強東", 33, 3000.82)); list.add(new Employee(1004, "雷軍", 26, 7657.37)); list.add(new Employee(1005, "李彥宏", 65, 5555.32)); list.add(new Employee(1006, "比爾蓋茨", 42, 9500.43)); list.add(new Employee(1007, "任正非", 26, 4333.32)); list.add(new Employee(1008, "扎克伯格", 35, 2500.32)); return list; } }
6.
/** * 方法引用的使用 * * 1.使用情境:當要傳遞給Lambda體的操作,已經有實現的方法了,可以使用方法引用! * * 2.方法引用,本質上就是Lambda表達式,而Lambda表達式作爲函數式接口的實例。所以 * 方法引用,也是函數式接口的實例。 * * 3. 使用格式: 類(或對象) :: 方法名 * * 4. 具體分爲如下的三種情況: * 情況1 對象 :: 非靜態方法 * 情況2 類 :: 靜態方法 * * 情況3 類 :: 非靜態方法 * * 5. 方法引用使用的要求:要求接口中的抽象方法的形參列表和返回值類型與方法引用的方法的 * 形參列表和返回值類型相同!(針對於情況1和情況2) */ public class MethodRefTest { // 情況一:對象 :: 實例方法 //Consumer中的void accept(T t) //PrintStream中的void println(T t) @Test public void test1() { Consumer<String> con1 = str -> System.out.println(str); con1.accept("北京"); System.out.println("*******************"); PrintStream ps = System.out; Consumer<String> con2 = ps::println; con2.accept("beijing"); } //Supplier中的T get() //Employee中的String getName() @Test public void test2() { Employee emp = new Employee(1001,"Tom",23,5600); Supplier<String> sup1 = () -> emp.getName(); System.out.println(sup1.get()); System.out.println("*******************"); Supplier<String> sup2 = emp::getName; System.out.println(sup2.get()); } // 情況二:類 :: 靜態方法 //Comparator中的int compare(T t1,T t2) //Integer中的int compare(T t1,T t2) @Test public void test3() { Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2); System.out.println(com1.compare(12,21)); System.out.println("*******************"); Comparator<Integer> com2 = Integer::compare; System.out.println(com2.compare(12,3)); } //Function中的R apply(T t) //Math中的Long round(Double d) @Test public void test4() { Function<Double,Long> func = new Function<Double, Long>() { @Override public Long apply(Double d) { return Math.round(d); } }; System.out.println("*******************"); Function<Double,Long> func1 = d -> Math.round(d); System.out.println(func1.apply(12.3)); System.out.println("*******************"); Function<Double,Long> func2 = Math::round; System.out.println(func2.apply(12.6)); } // 情況三:類 :: 實例方法 (有難度) // Comparator中的int comapre(T t1,T t2) // String中的int t1.compareTo(t2) @Test public void test5() { Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2); System.out.println(com1.compare("abc","abd")); System.out.println("*******************"); Comparator<String> com2 = String :: compareTo; System.out.println(com2.compare("abd","abm")); } //BiPredicate中的boolean test(T t1, T t2); //String中的boolean t1.equals(t2) @Test public void test6() { BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2); System.out.println(pre1.test("abc","abc")); System.out.println("*******************"); BiPredicate<String,String> pre2 = String :: equals; System.out.println(pre2.test("abc","abd")); } // Function中的R apply(T t) // Employee中的String getName(); @Test public void test7() { Employee employee = new Employee(1001, "Jerry", 23, 6000); Function<Employee,String> func1 = e -> e.getName(); System.out.println(func1.apply(employee)); System.out.println("*******************"); Function<Employee,String> func2 = Employee::getName; System.out.println(func2.apply(employee)); } }
7.
/** * 一、構造器引用 * 和方法引用類似,函數式接口的抽象方法的形參列表和構造器的形參列表一致。 * 抽象方法的返回值類型即爲構造器所屬的類的類型 * * 二、數組引用 * 大家可以把數組看做是一個特殊的類,則寫法與構造器引用一致。 */ public class ConstructorRefTest { //構造器引用 //Supplier中的T get() //Employee的空參構造器:Employee() @Test public void test1(){ Supplier<Employee> sup = new Supplier<Employee>() { @Override public Employee get() { return new Employee(); } }; System.out.println("*******************"); Supplier<Employee> sup1 = () -> new Employee(); System.out.println(sup1.get()); System.out.println("*******************"); Supplier<Employee> sup2 = Employee :: new; System.out.println(sup2.get()); } //Function中的R apply(T t) @Test public void test2(){ Function<Integer,Employee> func1 = id -> new Employee(id); Employee employee = func1.apply(1001); System.out.println(employee); System.out.println("*******************"); Function<Integer,Employee> func2 = Employee :: new; Employee employee1 = func2.apply(1002); System.out.println(employee1); } //BiFunction中的R apply(T t,U u) @Test public void test3(){ BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name); System.out.println(func1.apply(1001,"Tom")); System.out.println("*******************"); BiFunction<Integer,String,Employee> func2 = Employee :: new; System.out.println(func2.apply(1002,"Tom")); } //數組引用 //Function中的R apply(T t) @Test public void test4(){ Function<Integer,String[]> func1 = length -> new String[length]; String[] arr1 = func1.apply(5); System.out.println(Arrays.toString(arr1)); System.out.println("*******************"); Function<Integer,String[]> func2 = String[] :: new; String[] arr2 = func2.apply(10); System.out.println(Arrays.toString(arr2)); } }