日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

《Java 8 实战》(二)—— Lambda

發布時間:2023/11/27 生活经验 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Java 8 实战》(二)—— Lambda 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Lambda表達式可以理解為簡潔地表示可傳遞的匿名函數的一種方式:它沒有名稱,但它有參數列表/函數主體/返回類型,可能還有一個可以拋出的異常列表。

?

Lambda表達式由參數/箭頭和主體組成:

(Apple a1, Apple a2)  -> a1.getWeight().compareTo(a2.getWeight());

?

之前的代碼形式:

Comparator<Apple> byWeight = new Comparator<Apple>() {
  public int compare(Apple a1, Apple a2) {

    return a1.getWeight().compareTo(a2.getWeight());

  }

}

?

Java 8 中有效的Lambda表達式:

1, ?(String s) -> s.length()

  具有一個String類型的參數,并返回一個int。Lambda表達式沒有return語句,因為已經隱含了return。

2, ?(Apple a) -> a.getWeight() > 150

  參數為Apple類型,返回一個boolean類型。

3, ?(int x, int y) -> {

    System.out.println("Result");

    System.out.println(x+y);

  }

  該Lambda表達式具有兩個int類型的參數而沒有返回值。Lambda表達式可以包含多行語句。

  () -> {return "Mario";}

  該Lambda表達式也是有效的。

4, () - > 42

  該Lambda表達式沒有參數,返回一個int

5, (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

  該表達式具有兩個Apple類型的參數,返回一個int

?

無效Lambda表達式:

(Integer i) -> return "Alan" + i;

(String s) -> {"IronMan";}

第一個表達式中,return是一個控制流語句。要使得這個語句有效,需要加上花括號。

第二個表達式中,"IronMan" 是一個表達式,不是語句。要使得此Lambda有效,可以去除花括號和分號。

?

Lambda基本語法:

(parameters) -> expression

or

(parameters) -> { statements;}

?

可以使用Lambda表達式的地方 ——?函數式接口

  只有在接受函數式接口的地方才可以使用Lambda表達式。

  函數式接口就是只定義一個抽象方法的接口。如Comparator和Runnable接口。

  Lambda表達式可以直接以內聯的形式為函數式接口的抽象方法提供實現,并把整個表達式作為函數式接口的實例。

  函數式接口的抽象方法的簽名就是Lambda表達式的簽名。這種抽象方法叫做函數描述符。

  新的Java API中,函數式接口帶有@FunctionalInterface的標注。如果用@FunctionalInterface定義了一個接口,但它卻不是函數式接口的話,便一起將返回一個提示原因的錯誤,例如“Multiple non-overriding abstract methods found in interface Foo”,表明存在多個抽象方法。

?

使用Lambda表達式的步驟:

1,行為參數化:

  提取Lambda表達式,設計好參數,函數主體和返回值。

2,使用函數式接口來傳遞行為:

  創建一個能匹配Lambda表達式的函數式接口I,并把這個接口作為參數傳遞給需要使用Lambda表達式的函數M。

3,執行函數式接口中的行為

  在函數M中調用接口I中的抽象函數

4,傳遞Lambda表達式

?

常用函數式接口:

Java 8 以前已有的函數式接口:

  Comparable

  Runnable

  Callable

Java 8 在java.util.function包中引入的新的函數式接口:

  Predicate  

@FunctionalInterface
public interface Predicate<T>{boolean test(T t);
}
public static <T> List<T> filter(List<T> list, Predicate<T> p) {List<T> results = new ArrayList<>();for(T s: list){if(p.test(s)){results.add(s);}}return results;
}
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

  Consumer  

  

@FunctionalInterface
public interface Consumer<T>{void accept(T t);
}
public static <T> void forEach(List<T> list, Consumer<T> c){    for(T i: list){c.accept(i);}
}
forEach(Arrays.asList(1,2,3,4,5),(Integer i) -> System.out.println(i));

  Function

@FunctionalInterface
public interface Function<T, R>{R apply(T t);
}
public static <T, R> List<R> map(List<T> list,Function<T, R> f) {List<R> result = new ArrayList<>();for(T s: list){result.add(f.apply(s));}return result;
}List<Integer> l = map(Arrays.asList("lambdas","in","action"),(String s) -> s.length());

?

?

Lambda及函數式接口例子

使用案例?Lambda的例子?對應的函數式接口
布爾表達式?(List<String> list) -> list.isEmpty()? Predicate<List<String>>
創建對象?() -> new Apple(10)Supplier<Apple>
消費一個對象(Apple a) -> System.out.println(a.getWeight())

?

Consumer<Apple>

?從一個對象中選擇/提取?(String s) -> s.length()?

Function<String, Integer>或
ToIntFunction<String>

?合并兩個值?(int a, int b) -> a * b?IntBinaryOperator
比較兩個對象??

(Apple a1, Apple a2) ->
a1.getWeight().compareTo(a2.getWeight())

?

Comparator<Apple>或
BiFunction<Apple, Apple, Integer>
或ToIntBiFunction<Apple, Apple>

?

函數式接口異常:

任何函數式接口都不允許拋出受檢異常(checked Exception。 如果需要Lambda表達式拋出異常,有兩種方式:

1,定義一個自己的函數式接口,并聲明受檢異常:?

@FunctionalInterface
public interface BufferedReaderProcessor {String process(BufferedReader b) throws IOException;
}
BufferedReaderProcessor p = (BufferedReader br) -> br.readLine();

2,把Lambda包在一個try/cache塊中。

Function<BufferedReader, String> f = (BufferedReader b) -> {try {return b.readLine();}catch(IOException e) {throw new RuntimeException(e);}
};

?

Lambda表達式類型檢查:

Lambda的類型是從使用Lambda的上下文推斷出來的。上下文中Lambda表達式需要的類型成為目標類型。例如:?

List<Apple> heavierThan150g = filter(inventory, (Apple a) -> a.getWeight() > 150);

類型檢查過程:

1,找出filter方法的聲明

2,要求它是predicate<Apple>對象的第二個正式參數。

3,Predicate<Apple>是一個函數式接口,定義了一個叫做test的抽象方法。

4,test方法描述了一個函數描述符,它可以接受一個Apple,并返回一個boolean.

5, filter的任何實際參數都匹配這個要求。

?

Lambda表達式類型推斷:

編譯器可以了解Lambda表達式的參數類型,這樣可以在Lambda語法中省去標注參數類型,即:

List<Apple> greenApples = filter(inventory, a -> "green".equals(a.getColor()));

但有時顯式寫出類型更易讀,有時候去掉更易讀,需要自己權衡。

當Lambda僅有一個類型需要推斷的參數時,參數名稱兩邊的括號也可以省略。

?

方法引用:

參考:http://www.cnblogs.com/chenpi/p/5885706.html

什么是方法引用

  簡單地說,就是一個Lambda表達式。在Java 8中,我們會使用Lambda表達式創建匿名方法,但是有時候,我們的Lambda表達式可能僅僅調用一個已存在的方法,而不做任何其它事,對于這種情況,通過一個方法名字來引用這個已存在的方法會更加清晰,Java 8的方法引用允許我們這樣做。方法引用是一個更加緊湊,易讀的Lambda表達式,注意方法引用是一個Lambda表達式,其中方法引用的操作符是雙冒號"::"。

方法引用例子

?先看一個例子

首先定義一個Person類,如下:

package methodreferences;import java.time.LocalDate;public class Person
{public Person(String name, LocalDate birthday){this.name = name;this.birthday = birthday;}String name;LocalDate birthday;public LocalDate getBirthday(){return birthday;}public static int compareByAge(Person a, Person b){return a.birthday.compareTo(b.birthday);}@Overridepublic String toString(){return this.name;}
}

假設我們有一個Person數組,并且想對它進行排序,這時候,我們可能會這樣寫:

原始寫法

package methodreferences;import java.time.LocalDate;
import java.util.Arrays;
import java.util.Comparator;public class Main
{static class PersonAgeComparator implements Comparator<Person> {public int compare(Person a, Person b) {return a.getBirthday().compareTo(b.getBirthday());}}public static void main(String[] args){Person[] pArr = new Person[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};Arrays.sort(pArr, new PersonAgeComparator());System.out.println(Arrays.asList(pArr));}
}

其中,Arrays類的sort方法定義如下:

public static <T> void sort(T[] a, Comparator<? super T> c)

這里,我們首先要注意Comparator接口是一個函數式接口,因此我們可以使用Lambda表達式,而不需要定義一個實現Comparator接口的類,并創建它的實例對象,傳給sort方法。

使用Lambda表達式,我們可以這樣寫:

改進一,使用Lambda表達式,未調用已存在的方法

package methodreferences;import java.time.LocalDate;
import java.util.Arrays;public class Main
{public static void main(String[] args){Person[] pArr = new Person[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};Arrays.sort(pArr, (Person a, Person b) -> {return a.getBirthday().compareTo(b.getBirthday());});System.out.println(Arrays.asList(pArr));}
}

然而,在以上代碼中,關于兩個人生日的比較方法在Person類中已經定義了,因此,我們可以直接使用已存在的Person.compareByAge方法。

改進二,使用Lambda表達式,調用已存在的方法

package methodreferences;import java.time.LocalDate;
import java.util.Arrays;public class Main
{public static void main(String[] args){Person[] pArr = new Person[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};Arrays.sort(pArr, (a, b) -> Person.compareByAge(a, b));System.out.println(Arrays.asList(pArr));}
}

因為這個Lambda表達式調用了一個已存在的方法,因此,我們可以直接使用方法引用來替代這個Lambda表達式,

改進三,使用方法引用

package methodreferences;import java.time.LocalDate;
import java.util.Arrays;public class Main
{public static void main(String[] args){Person[] pArr = new Person[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};Arrays.sort(pArr, Person::compareByAge);System.out.println(Arrays.asList(pArr));}
}

在以上代碼中,方法引用Person::compareByAge在語義上與Lambda表達式 (a, b) -> Person.compareByAge(a, b) 是等同的,都有如下特性:

  • 真實的參數是拷貝自Comparator<Person>.compare方法,即(Person, Person);
  • 表達式體調用Person.compareByAge方法;

四種方法引用類型

靜態方法引用

我們前面舉的例子Person::compareByAge就是一個靜態方法引用。

特定實例對象的方法引用

如下示例,引用的方法是myComparisonProvider?對象的compareByName方法;

        class ComparisonProvider{public int compareByName(Person a, Person b){return a.getName().compareTo(b.getName());}public int compareByAge(Person a, Person b){return a.getBirthday().compareTo(b.getBirthday());}}ComparisonProvider myComparisonProvider = new ComparisonProvider();Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);

任意對象(屬于同一個類)的實例方法引用

如下示例,這里引用的是字符串數組中任意一個對象的compareToIgnoreCase方法。

        String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };Arrays.sort(stringArray, String::compareToIgnoreCase);

構造方法引用

如下示例,這里使用了關鍵字new,創建了一個包含Person元素的集合。

Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
transferElements方法的定義如下,功能為集合拷貝,
public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>DEST transferElements(SOURCE sourceCollection,Supplier<DEST> collectionFactory) {DEST result = collectionFactory.get();for (T t : sourceCollection) {result.add(t);}return result;
}

什么場景適合使用方法引用

當一個Lambda表達式調用了一個已存在的方法

什么場景不適合使用方法引用

當我們需要往引用的方法傳其它參數的時候,不適合,如下示例:

IsReferable demo = () -> ReferenceDemo.commonMethod("Argument in method.");

?

?

Lambda 和 方法引用實戰

第一步,傳遞代碼

public class AppleComparator implements Comparator<Apple> {public int compare(Apple a1, Apple a2) {return a1.getWeight().compareTo(a2.getWeight());}
}inventory.sort(new AppleComparator());

第二步,使用匿名類

inventory.sort(new Comparator<Apple>() {public int compare(Apple a1, Apple a2) {return a1.getWeight().compareTo(a2.getWeight());}
})

第三步,使用Lambda表達式

inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

Java編譯器可以根據Lambda出現的上下文來推斷Lambda表達式參數的類型,所以可以改寫為:

inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));

Comparator具有一個叫做comparing的靜態方法,可以接受一個Function來提取Comparable鍵值,并生成一個Comparator對象,如下:

Comparator<Apple> c = Comparator.comparing((Apple a) -> a.getWeight());

所以再次改寫:

inventory.sort(comparing((a) -> a.getWeight()));

第四步,使用方法引用

inventory.sort(comparing(Apple::getWeight));

?

復合Lambda表達式

1,比較器復合

  a,逆序

inventory.sort(comparing(Apple::getWeight).reversed())

  b, 比較器鏈

inventory.sort(comparing(Apple::getWeight).reversed().thenComparing(Apple::getCountry));

2, 謂詞復合

  a,negate

Predicate<Apple> notRedApple = redApple.negate();

  b, and

Predicate<Apple> redAndHeavyApple = redApple.and(a -> a.getWeight() > 150);

  c, or

Predicate<Apple> redAAndHeavyAppleOrGreen = redApple.and(a -> a.getWeight() > 150).or(a -> "green".equals(a.getColor()));

3, 函數復合

  a,andThen 相當于g(f(x))

Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g);
int result = h.apply(1); // result = 4

  b, compose 相當于f(g(x))

Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.compose(g);
int result = h.apply(1); // result = 3

?

轉載于:https://www.cnblogs.com/IvySue/p/6737133.html

總結

以上是生活随笔為你收集整理的《Java 8 实战》(二)—— Lambda的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。