jdk1.8 新特性之 lambda表示式

dounine發表於2017-04-23

我們首先看一個java實現多執行緒的lambda表示式的例子

常規

Runnable runnable = new Runnable(){
            @Override
            public void run() {
                System.out.println("多執行緒");
            }};

lambda形式

Runnable runnable = () -> {
            System.out.println("多執行緒");
        };

簡潔
此方法使用的場景只能是實現的方法中只有一行語句。

Runnable runnable = () -> System.out.println("多執行緒");

Lambda在Collections中的用法

public class StreamExample {

    public static void main(String[] args) {

        List<Integer> myList = new ArrayList<>();
        for(int i=0; i<100; i++) myList.add(i);

        //有序流
        Stream<Integer> sequentialStream = myList.stream();

        //並行流
        Stream<Integer> parallelStream = myList.parallelStream();

        //使用lambda表示式,過濾大於90的數字
        Stream<Integer> highNums = parallelStream.filter(p -> p > 90);
        //lambdag表示式 forEach迴圈
        highNums.forEach(p -> System.out.println("最大數 並行="+p));

        Stream<Integer> highNumsSeq = sequentialStream.filter(p -> p > 90);
        highNumsSeq.forEach(p -> System.out.println("最大數 有序="+p));

    }

}

輸出結果

最大數 並行=91
最大數 並行=96
最大數 並行=93
最大數 並行=98
最大數 並行=94
最大數 並行=95
最大數 並行=97
最大數 並行=92
最大數 並行=99
最大數 有序=91
最大數 有序=92
最大數 有序=93
最大數 有序=94
最大數 有序=95
最大數 有序=96
最大數 有序=97
最大數 有序=98
最大數 有序=99

為什麼要使用Lambda表示式

1.簡化程式碼行數
2.順序執行或並行執行
以下為例子之間的對照

//傳統形式
private static boolean isPrime(int number) {        
    if(number < 2) return false;
    for(int i=2; i<number; i++){
        if(number % i == 0) return false;
    }
    return true;
}
//使用表示式的
private static boolean isPrime(int number) {        
    return number > 1
            && IntStream.range(2, number).noneMatch(
                    index -> number % index == 0);
}

為了更好的可讀性,我們還可以這麼寫

private static boolean isPrime(int number) {
    IntPredicate isDivisible = index -> number % index == 0;

    return number > 1
            && IntStream.range(2, number).noneMatch(
                    isDivisible);
}

我們來看一個計算數字集合總合的例子,它有一個引數將用來傳遞表示式後處理得到最終的結果。

public static int sumWithCondition(List<Integer> numbers, Predicate<Integer> predicate) {
        return numbers.parallelStream()
                .filter(predicate)
                .mapToInt(i -> i)
                .sum();
    }

比如我們將傳遞這樣的如下條件

//統計所有數字總合
sumWithCondition(numbers, n -> true)
//統計所有偶數總合
sumWithCondition(numbers, i -> i%2==0)
//統計所有大於5的總合
sumWithCondition(numbers, i -> i>5)

接下來我再來看一個更加偷懶的Lambda表示式

//找出3-11之間最大的奇數,並求它的平方
private static int findSquareOfMaxOdd(List<Integer> numbers) {
        int max = 0;
        for (int i : numbers) {
            if (i % 2 != 0 && i > 3 && i < 11 && i > max) {
                max = i;
            }
        }
        return max * max;
    }

我們使用Lambada重寫它

class NumberTest{
    public static int findSquareOfMaxOdd(List<Integer> numbers) {
            return numbers.stream()
                    .filter(NumberTest::isOdd)
                    .filter(NumberTest::isGreaterThan3)
                    .filter(NumberTest::isLessThan11)
                    .max(Comparator.naturalOrder())
                    .map(i -> i * i)
                    .get();
        }

        public static boolean isOdd(int i) {
            return i % 2 != 0;
        }

        public static boolean isGreaterThan3(int i){
            return i > 3;
        }

        public static boolean isLessThan11(int i){
            return i < 11;
        }
}

Lambada表示式例子

() -> {}                     // 沒有引數,沒有返回值

() -> 42                     // 沒有引數,方法體有表示式
() -> null                   // 沒有引數,方法體有表示式
() -> { return 42; }         // 沒有引數,方法體有返回值
() -> { System.gc(); }       // 沒有引數,有方法體

// 有多種返回值
() -> {
  if (true) return 10;
  else {
    int result = 15;
    for (int i = 1; i < 10; i++)
      result *= i;
    return result;
  }
}                          

(int x) -> x+1             // 單個引數
(int x) -> { return x+1; } // 單個引數,跟上面一樣
(x) -> x+1                 // 單個引數,跟下面一樣
x -> x+1                   

(String s) -> s.length()   
(Thread t) -> { t.start(); } 
s -> s.length()              
t -> { t.start(); }          

(int x, int y) -> x+y      // 多個引數,有返回值
(x,y) -> x+y               // 跟上面一樣
(x, final y) -> x+y        // 多個引數,有不能修改的引數
(x, int y) -> x+y          // 這個是非法的,不能混合寫

方法跟建構函式可以用下面這種方式

System::getProperty
System.out::println
"abc"::length
ArrayList::new
int[]::new

相關文章