java8 --Lambda 表達式

爲什麼使用 Lambda 表達式?
Lambda 是一個匿名函數,可以理解是一段可以傳遞的代碼(將代碼像數據一樣進行傳遞)。可以寫出更加簡潔、靈活的代碼。作爲一種更緊湊的代碼風格,使 Java 的語言表達能力得到了提升。

import org.junit.Test;

import java.util.Comparator;
import java.util.TreeSet;

public class TestLembda {

    // 原來的匿名內部類
    @Test
    public void test1 () {
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1, o2);
            }
        };

        TreeSet<Integer> treeSet = new TreeSet<>(comparator);
    }

    // Lambda 表達式
    @Test
    public void test2 () {
        Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
        TreeSet<Integer> treeSet = new TreeSet<>(comparator);
    }
}

一、Lambda 表達式基礎語法
Java 8 中引入了一個新的操作符 “ ->” 該操作符稱爲箭頭操作符或 Lambda 操作符,箭頭操作符將 Lambda 拆分成兩部分
左側:Lambda 表達式的參數列表,對應接口中抽象方法的參數列表
右側:Lambda 表達式所需要執行的功能,即 Lambda 體,對抽象方法的實現

語法格式格式一:方法無參數無返回值

()-> System.out.println("Hello, Lambda!");
@Test
public void test1 () {
    int num = 0; // 局部內部類使用的變量再 jdk 1.7 之前必須是 final,現在依然是 final 只是可以省略
    // final 的變量不允許修改

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // 內部類使用的變量
            System.out.println("Hello, world!" + num);
        }
    };
    runnable.run();
    // num++;
    System.out.println("---------------------------------------");

    Runnable runnable1 = () -> System.out.println("Hello, world!");
    runnable1.run();
}

語法格式二:有一個參數並且無返回值

@Test
public void test2 () {
    Consumer<String> consumer = (x) -> System.out.println(x);
    consumer.accept("Hello, world!");
}

語法格式三:只有一個參數,小括號可以省略
語法格式四:有兩個以上的參數,有返回值,並且 Lambda 體中有多條語句
多條語句一定要在一對大括號內

@Test
public void test3 () {
    Comparator<Integer> com = (x, y) -> {
        System.out.println("函數式接口");
        return Integer.compare(x, y);
    };
}

語法格式五:有兩個以上的參數,有返回值,若 Lambda 體中只有一條語句
返回值和大括號都可以省略

語法格式六:
Lambda 表達式的參數列表的數據類型可以忽略不寫,因爲 JVM 編譯器通過上下文推斷出數據類型,即 “類型推斷”。根據接口中定義的數據類型,當然瞭如果是泛型,根據指定的 T 來推斷。

Lambda 表達式需要函數時接口的支持

函數式接口:接口中只有一個抽象方法的接口(多了沒法直接映射過去),可以使用 @FunctionalInterface 修飾,用來檢查是否是函數式接口。

public interface MyCalculate<T, R> {
    public R compute(T t1, T t2);
}
// 調用 Collections.sort()  方法,通過定製排序比較兩個 Employee (先按照年齡比,年齡相同按照姓名比)
// 使用 Lambda 作爲參數傳遞
@Test
public void test() {
    List<Employee> employees = Arrays.asList(
            new Employee("張三", 18, 99999.99),
            new Employee("李四", 50, 2222.22),
            new Employee("王五", 16, 666.66),
            new Employee("趙六", 16, 666.66),
            new Employee("錢六", 15, 3333.33));
    Comparator<Employee> comparator = (e1, e2) -> {
        if (e1.getAge().equals(e2.getAge())) {
            return e1.getName().compareTo(e2.getName());
        } else {
            return Integer.compare(e1.getAge(), e2.getAge());
        }
    };
    // 自定義排序,前一個是 List 集合,後一個是自定義的排序方法
    Collections.sort(employees, comparator);
    for (Employee employee : employees) {
        System.out.println(employee);
    }
}

// 聲明函數式接口,接口中聲明抽象方法,public String getValue(String str)
// 聲明類 TestLambda,類中編寫方法使用接口作爲參數,將一個字符串轉換成大寫,並作爲方法的返回值
// 再將一個字符串的第 2 個和第 4 個索引位置進行截取子串
@Test
public void test2() {
    String str = "abcdefghijk";
    System.out.println(handleStr(str, (s) -> s.toUpperCase()));

    System.out.println("----------------------------------");
    System.out.println(handleStr(str, (s) -> s.substring(2, 4)));
}

public String handleStr(String str, HandleString handleString) {
    return handleString.getValue(str);
}

// 聲明一個帶兩個反省的函數式接口,泛型類型爲<T, R> T 爲參數,R 爲返回值
// 接口中聲明對應的抽象方法
// 再 TestLambda 類中聲明方法,使用接口作爲參數,計算兩個 long 類型參數的和
// 再計算兩個 long 類型的乘積
@Test
public void test3 () {
    System.out.println(compute(12L, 14L, (a, b) -> a + b));
    System.out.println(compute(13L, 44L, (a, b) -> a * b));
}

public long compute(Long num1, Long num2, MyCalculate<Long, Long> cal) {
    return cal.compute(num1, num2);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章