java8中Lambda表示式實現Runnable介面寫法

java8中Lambda表示式實現Runnable介面寫法

例1 用Lambda表示式實現Runnable介面

Java程式碼

//Java 之前版本寫法:

new

Thread(

new

Runnable() {

@Override

public

void

run() {

System。out。println(“Before Java8, too much code for too little to do”);

}

})。start();

2、//Java 8 版本

Lambda

寫法:

new

Thread( () -> System。out。println(“In Java8, Lambda expression rocks !!”) )。start();

輸出:

too much code, for too little to do

Lambda expression rocks !!

這個例子使我們學到了java8中Lambda表示式的書寫方式:

(引數) -> 表示式

(引數) -> 語句

(引數) -> { 語句 }

為了鞏固知識,下面為你介紹9個例子關於Lambda表示式寫法

例如,如果你的方法只是在控制檯列印資訊,則可以這麼寫:

Java程式碼

() -> System。out。println(“Hello Lambda Expressions”);

如果你的方法接收兩個引數,那麼:

Java程式碼

int

even,

int

odd) -> even + odd

順帶提一句,一般來說在Lambda表示式中要儘量保持變數的簡潔性。這會使你的程式碼簡短而能保持在一行之內。所以像上面的程式碼可以選擇變數名類似a,b或者x,y之類的,比起even和odd來會更好。

java8中Lambda表示式實現Runnable介面寫法

顯示在電腦螢幕上的計算機程式原始碼,可用作網路科技等素材或背景。

例2 用Lambda表示式寫事件監聽程式

要是你用過Swing API,那就少不了事件監聽程式碼,這是使用匿名類的經典例子。現在我們可以用Lambda表示式來抒寫更好的事件處理程式碼。

Java程式碼

// Before Java 8:

JButton show =

new

JButton(“Show”);

show。addActionListener(

new

ActionListener() {

@Override

public

void

actionPerformed(ActionEvent e) {

System。out。println(“Event handling without lambda expression is boring”);

}

});

// Java 8 way:

show。addActionListener((e) -> {

System。out。println(“Light, Camera, Action !! Lambda expressions Rocks”);

});

另外一個常用匿名類的地方是給Collections.sort()方法提供自定義的Comparator介面實現。這個地方也可以用Lambda表示式。

例3 用Lambda表示式進行List迭代

Java程式碼

//Prior Java 8 :

List features = Arrays。asList(“Lambdas”, “Default Method”, “Stream API”, “Date and Time API”);

for

(String feature : features) {

System。out。println(feature);

}

//In Java 8:

List features = Arrays。asList(“Lambdas”, “Default Method”, “Stream API”, “Date and Time API”);

features。forEach(n -> System。out。println(n));

// 用java8的方法引用更好,方法引用由::(雙冒號)運算子來完成,看起來像c++中的作用域運算子

Java程式碼

features。forEach(System。out::println);

輸出:

Lambdas

Default Method

Stream API

Date and Time API

例4 使用Lambda表示式和函式式介面Predicate

除了提供函數語言程式設計語言級別的支援外,java8同時也新增了一個新的包java.util.function。其中包含了許多類來支援java函數語言程式設計。其中之一是Predicate介面,使用這個介面和lamb表示式就可以以更少的程式碼為API方法新增更多的動態行為。

以下是Predicate的使用範例,展示了過濾集合資料的許多共性。

Java程式碼

public

static

void

main(args[]){

List languages = Arrays。asList(“Java”, “Scala”, “C++”, “Haskell”, “Lisp”);

System。out。println(“Languages which starts with J :”);

filter(languages, (str)->str。startsWith(“J”));

System。out。println(“Languages which ends with a ”);

filter(languages, (str)->str。endsWith(“a”));

System。out。println(“Print all languages :”);

filter(languages, (str)->

true

);

System。out。println(“Print no language : ”);

filter(languages, (str)->

false

);

System。out。println(“Print language whose length greater than 4:”);

filter(languages, (str)->str。length() > 4);

}

public

static

void

filter(List names, Predicate condition) {

for

(String name: names) {

if

(condition。test(name)) {

System。out。println(name + “ ”);

}

}

}

輸出:

Languages which starts with J :

Java

Languages which ends with a

Java

Scala

Print all languages :

Java

Scala

C++

Haskell

Lisp

Print no language :

Print language whose length greater than 4:

Scala

Haskell

Java程式碼

//更佳的方式

public

static

void

filter(List names, Predicate condition) {

names。stream()。filter((name) -> (condition。test(name)))。forEach((name) -> {

System。out。println(name + “ ”);

});

}

可以看到Stream API的filter方法也接受一個Predicate,意味著可以用內聯程式碼直接替換我們自定義的filter()方法。這就是Lambda表示式的威力所在。除此之外Predicate介面也可以測試多個條件,將會在下面的例子中加以說明。

例5: Lambda表示式結合Predicate

就像上個例子所說,Predicate允許組合兩個以上的條件,它提供了類似於邏輯與和或的操作and(),or()和xor(),這些方法可以用來組合傳遞到filter方法中的多個條件。例如為了獲取所有以J開頭並有四個字元長度的語言,可以定義兩個單獨的Predicate例項覆蓋每個條件然後用and方法將它們組合在一起。看例子:

Java程式碼

Predicate startsWithJ = (n) -> n。startsWith(“J”);

Predicate fourLetterLong = (n) -> n。length() == 4;

names。stream()。filter(startsWithJ。and(fourLetterLong))。forEach((n) -> System。out。print(“\nName, which starts with ‘J’ and four letter long is : ” + n));

類似可以用or或者xor。這個例子也強調了單獨用或者按需組合用Predicate的重要性。簡而言之用Predicate和Lambda表示式的優勢你可以寫的更少做得更多。

例6 Map和Reduce的例子

6.1 Map

在這個例子中,我們要將costBeforeTax的每個元素以加上他們的增值稅。傳遞一個Lambda表示式給map方法使之應用於每個元素,之後再用forEach列印結果。

Java程式碼

// Without lambda expressions:

List costBeforeTax = Arrays。asList(100, 200, 300, 400, 500);

for

(Integer cost : costBeforeTax) {

double

price = cost + 。12*cost;

System。out。println(price);

}

// With Lambda expression:

List costBeforeTax = Arrays。asList(100, 200, 300, 400, 500);

costBeforeTax。stream()。map((cost) -> cost + 。12*cost)。forEach(System。out::println);

輸出

112。0

224。0

336。0

448。0

560。0

112。0

224。0

336。0

448。0

560。0

6.2 Reduce

還有另外一個函式reduce可以將所有值轉換為一個值。map跟reduce操作是函數語言程式設計的核心,reduce也被稱作摺疊操作。reduce並不是一種新的操作,在SQL中我們用的一些聚集函式比如sum,avg,count等他們實際上也是reduce操作,因為他們也是將多個值進行操作然後返回一個值。Stream API定義了reduce函式,可以接受一個Lambda表示式然後組合所有值。Stream類中像IntStream都有內建的方法像average(), count(), sum(), mapToLong(), mapToDouble()等轉換方法。我們可以用內建的方法也可以自定義。

Java程式碼

// Old way:

List costBeforeTax = Arrays。asList(100, 200, 300, 400, 500);

double

total = 0;

for

(Integer cost : costBeforeTax) {

double

price = cost + 。12*cost;

total = total + price;

}

System。out。println(“Total : ” + total);

// New way:

List costBeforeTax = Arrays。asList(100, 200, 300, 400, 500);

double

bill = costBeforeTax。stream()。map((cost) -> cost + 。12*cost)。reduce((sum, cost) -> sum

+ cost)。get();

System。out。println(“Total : ” + bill);

輸出

Total : 1680。0

Total : 1680。0

例7 用filter建立一個字串List

在java開發中對大的集合進行過濾是常用的操作。用Lambda表示式和Stream API會讓操作變得簡單易懂。

Stream提供了一個filter()方法,接受一個Predicate物件。這意味著可以傳遞一個Lambda表示式作為過濾邏輯,看例子:

Java程式碼

//建立一個長度大於兩個字元的字串List

List filtered = strList。stream()。filter(x -> x。length()>

2)。collect(Collectors。toList());

System。out。printf(“Original List : %s, filtered list : %s %n”, strList, filtered);

輸出 :

Original List : [abc, , bcd, , defg, jk], filtered list : [abc, bcd, defg]

例8 給每個List元素應用函式

在工作中我們經常會碰到這樣的情況:給List中每個元素加以一定的操作例如乘以或者除以某個值等。這些操作用map方法再好不過了,我們可以將轉換邏輯以Lambda表示式傳給map方法來應用於每個元素:

//將字串轉為大寫然後用逗號連起來

Java程式碼

List G7 = Arrays。asList(“USA”, “Japan”, “France”, “Germany”, “Italy”,“U。K。”,“Canada”);

String G7Countries = G7。stream()。map(x -> x。toUpperCase())。collect(Collectors。joining(“, ”));

System。out。println(G7Countries);

輸出:

USA, JAPAN, FRANCE, GERMANY, ITALY, U。K。, CANADA

例9 複製不同值到子列表

本例演示如何利用Stream類的distinct方法過濾重複值到集合中。

Java程式碼

List numbers = Arrays。asList(9, 10, 3, 4, 7, 3, 4);

List distinct = numbers。stream()。map( i ->i*i)。distinct()。collect(Collectors。toList());

System。out。printf(“Original List : %s, Square Without duplicates : %s %n”, numbers, distinct);

輸出 :

Original List : [9, 10, 3, 4, 7, 3, 4], Square Without duplicates : [81, 100, 9, 16, 49]

例10 計算List中元素的最大,最小,和以及平均值

在Stream類中像IntStream, LongStream and DoubleStream有一個非常有用的方法summaryStattics(),返回IntSummaryStatistics, LongSummaryStatistics or DoubleSummaryStatistics其描述了這個流中元素的統計資料。下面的例子中我們用這個方法來計算一個List中的最大最小值總和以及均值:

Java程式碼

List primes = Arrays。asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);

IntSummaryStatistics stats = primes。stream()。mapToInt((x) -> x)。summaryStatistics();

System。out。println(“Highest prime number in List : ” + stats。getMax());

System。out。println(“Lowest prime number in List : ” + stats。getMin());

System。out。println(“Sum of all prime numbers : ” + stats。getSum());

System。out。println(“Average of all prime numbers : ” + stats。getAverage());

輸出:

Highest prime number in List : 29

Lowest prime number in List : 2

Sum of all prime numbers : 129

Average of all prime numbers : 12。9