国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

《Java8實(shí)戰(zhàn)》-第三章讀書筆記(Lambda表達(dá)式-01)

longshengwang / 1175人閱讀

摘要:之前,使用匿名類給蘋果排序的代碼是的,這段代碼看上去并不是那么的清晰明了,使用表達(dá)式改進(jìn)后或者是不得不承認(rèn),代碼看起來跟清晰了。這是由泛型接口內(nèi)部實(shí)現(xiàn)方式造成的。

# Lambda表達(dá)式
在《Java8實(shí)戰(zhàn)》中第三章主要講的是Lambda表達(dá)式,在上一章節(jié)的筆記中我們利用了行為參數(shù)化來因?qū)Σ粩嘧兓男枨螅詈笪覀円彩褂玫搅薒ambda,通過表達(dá)式為我們簡化了很多代碼從而極大地提高了我們的效率。那我們就來更深入的了解一下如何使用Lambda表達(dá)式,讓我們的代碼更加具有簡潔性和易讀性。

Lambda管中窺豹

什么是Lambda表達(dá)式?簡單的來說,Lambda表達(dá)式是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名,直接對應(yīng)其中的Lambda抽象(lambda abstraction),是一個(gè)匿名函數(shù),既沒有函數(shù)名的函數(shù)。Lambda表達(dá)式可以表示閉包(注意和數(shù)學(xué)傳統(tǒng)意義的不同)。你也可以理解為,簡潔的表示可傳遞的匿名函數(shù)的一種方式:它沒有名稱,但它有參數(shù)列表、函數(shù)主體、返回類型,可能還有一個(gè)可以拋出異常的列表。

有時(shí)候,我們?yōu)榱撕喕a而去使用匿名類,雖然匿名類能簡化一部分代碼,但是看起來很啰嗦。為了更好的的提高開發(fā)的效率以及代碼的簡潔性和可讀性,Java8推出了一個(gè)核心的新特性之一:Lambda表達(dá)式。

Java8之前,使用匿名類給蘋果排序的代碼:

apples.sort(new Comparator() {
    @Override
    public int compare(Apple o1, Apple o2) {
        return o1.getWeight().compareTo(o2.getWeight());
    }
});

是的,這段代碼看上去并不是那么的清晰明了,使用Lambda表達(dá)式改進(jìn)后:

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

或者是:

Comparator byWeight = Comparator.comparing(Apple::getWeight);

不得不承認(rèn),代碼看起來跟清晰了。要是你覺得Lambda表達(dá)式看起來一頭霧水的話也沒關(guān)系,我們慢慢的來了解它。

現(xiàn)在,我們來看看幾個(gè)Java8中有效的Lambda表達(dá)式加深對Lambda表達(dá)式的理解:

// 這個(gè)表達(dá)式具有一個(gè)String類型的參數(shù)并返回一個(gè)int,Lambda并沒有return語句,因?yàn)橐呀?jīng)隱含了return。
(String s) -> s.length() 

// 這個(gè)表達(dá)式有一個(gè)Apple類型的參數(shù)并返回一個(gè)boolean(蘋果重來是否大于150克)
(Apple a) -> a.getWeight() > 150

// 這個(gè)表達(dá)式具有兩個(gè)int類型二的參數(shù)并且沒有返回值。Lambda表達(dá)式可以包含多行代碼,不只是這兩行。
(int x, int y) -> {
    System.out.println("Result:");
    System.out.println(x + y);
}

// 這個(gè)表達(dá)式?jīng)]有參數(shù)類型,返回一個(gè)int。
() -> 250

// 顯式的指定為Apple類型,并對重量進(jìn)行比較返回int
(Apple a2, Apple a2) -> a1.getWeight.compareTo(a2.getWeight())

Java語言設(shè)計(jì)者選選擇了這樣的語法,是因?yàn)镃#和Scala等語言中的類似功能廣受歡迎。Lambda的基本語法是:

(parameters) -> expression

或者(請注意花括號):

(parameters) -> {statements;}

是的,Lambda表達(dá)式的語法看起來就是那么簡單。那我們繼續(xù)看幾個(gè)例子,看看以下哪幾個(gè)是有效的:

(1) () -> {}
(2) () -> "Jack"
(3) () -> {return "Jack"}
(4) (Interge i) -> return "Alan" + i;
(5) (String s) -> {"IronMan";}

正確答案是:(1)、(2)、(3)

原因:

(1) 是一個(gè)無參并且無返回的,類似與private void run() {}.

(2) 是一個(gè)無參并且返回的是一個(gè)字符串。

(3) 是一個(gè)無參,并且返回的是一個(gè)字符串,不過里面還可以繼續(xù)寫一些其他的代碼(利用顯式返回語句)。

(4) 它沒有使用使用顯式返回語句,所以它不能算是一個(gè)表達(dá)式。想要有效就必須加一對花括號,
(Interge i) -> {return "Alan" + i}

(5) "IronMan"很顯然是一個(gè)表達(dá)式,不是一個(gè)語句,去掉這一對花括號或者使用顯式返回語句即可有效。

在哪里以及如何使用Lambda

我們剛剛已經(jīng)看了很多關(guān)于Lambda表達(dá)式的語法例子,可能你還不太清楚這個(gè)Lambda表達(dá)式到底如何使用。

還記得在上一章的讀書筆記中,實(shí)現(xiàn)的filter方法中,我們使用的就是Lambda:

List heavyApples = filter(apples, (Apple apple) -> apple.getWeight() > 150);

我們可以在函數(shù)式接口上使用Lambda表達(dá)式,函數(shù)式接口聽起來很抽象,但是不用太擔(dān)心接下來就會解釋函數(shù)式接口是什么。

函數(shù)式接口

還記得第二章中的讀書筆記,為了參數(shù)化filter方法的行為使用的Predicate接口嗎?它就是一個(gè)函數(shù)式接口。什么是函數(shù)式接口?一言蔽之,函數(shù)式接口就是只定義了一個(gè)抽象方法的接口。例如JavaAPI中的:Comparator、Runnable、Callable:

public interface Comparable {
    public int compareTo(T o);
}

public interface Runnable {
    public abstract void run();
}

public interface Callable {
    V call() throws Exception;
}

當(dāng)然,不只是它們,還有很多一些其他的函數(shù)式接口。

函數(shù)式接口到底可以用來干什么?Lambda表達(dá)式允許你直接以內(nèi)聯(lián)的形式為函數(shù)式接口的抽象方法提供實(shí)例,并把整個(gè)表達(dá)式作為函數(shù)式接口的實(shí)例(具體來說,是函數(shù)式接口一個(gè)具體實(shí)現(xiàn)的實(shí)例)。你也可以使用匿名類實(shí)現(xiàn),只不過看來并不是那么的一目了然。使用匿名類你需要提供一個(gè)實(shí)例,然后在直接內(nèi)聯(lián)將它實(shí)例化。

通過下面的代碼,你可以來比較一下使用函數(shù)式接口和使用匿名類的區(qū)別:

// 使用Lambda表達(dá)式
Runnable r1 = () -> System.out.println("HelloWorld 1");

// 使用匿名類
Runnable r2 = new Runnable() {
    @Override
    public void run() {
        System.out.println("HelloWorld 2");
    }
};

// 運(yùn)行結(jié)果
System.out.println("Runnable運(yùn)行結(jié)果:");
// HelloWorld 1
process(r1);
// HelloWorld 2
process(r2);
// HelloWorld 3
process(() -> System.out.println("HelloWorld 3"));
        
private static void process(Runnable r) {
    r.run();
}

酷,從上面的代碼可以看出使用Lambda表達(dá)式你可以減少很多代碼同時(shí)也提高了代碼的可讀性而使用匿名類卻要四五行左右的代碼。

函數(shù)描述符

函數(shù)接口的抽象方法的前面基本上就是Lambda表達(dá)式的簽名。我們將這種抽象方法叫做函數(shù)描述符。例如,Runnable接口可以看作一個(gè)什么也不接受什么也不返回的函數(shù)簽名,因?yàn)樗挥幸粋€(gè)叫做run的抽象方法,這個(gè)方法沒有參數(shù)并且是無返回的。

使用函數(shù)式接口

函數(shù)式接口很有用,因?yàn)槌橄蠓椒ǖ暮灻梢悦枋鯨ambda表達(dá)式的簽名。函數(shù)式接口的抽象方法的簽名稱為函數(shù)描述符。

Predicate

在第一章的讀書筆記中,有提到過Predicate這個(gè)接口,現(xiàn)在我們來詳細(xì)的了解一下它。

java.util.function.Predicate接口定義了一個(gè)名字叫test的抽象方法,它接受泛型T對象,并返回一個(gè)boolean值。之前我們是創(chuàng)建了一個(gè)Predicate這樣的一個(gè)接口,現(xiàn)在我們所說到的這個(gè)接口和之前創(chuàng)建的一樣,現(xiàn)在我們不需要再去創(chuàng)建一個(gè)這樣的接口就直接可以使用了。在你需要表示一個(gè)涉及類型T的布爾表達(dá)式時(shí),就可以使用這個(gè)接口。比如,你可以定義一個(gè)接受String對象的Lambda表達(dá)式:

@FunctionalInterface
public interface Predicate {
    boolean test(T t);
}

private static  List filter(List list, Predicate predicate) {
    List result = new ArrayList<>();
    for (T t : list) {
        if (predicate.test(t)) {
            result.add(t);
        }
    }
    return result;
}

List strings = Arrays.asList("Hello", "", "Java8", "", "In", "Action");
Predicate nonEmptyStringPredicate = (String s) -> !s.isEmpty();

List stringList = filter(strings, nonEmptyStringPredicate);
// [Hello, Java8, In, Action]
System.out.println(stringList);

如果,你去查看Predicate這個(gè)接口的源碼你會發(fā)現(xiàn)有一些and或者or等等一些其他的方法,并且這個(gè)方法還有方法體,不過你目前無需關(guān)注這樣的方法,以后的文章將會介紹到為什么在接口中能定義有方法體的方法。

Consumer

java.util.function.Consumer定義了一個(gè)叫做accept的抽象方法,它接受泛型T的對象,并且是一個(gè)無返回的方法。你如果需要訪問類型T的對象,并對其執(zhí)行某些操作,就可以使用這個(gè)接口。比如,你可以用它來創(chuàng)建一個(gè)foreach方法,并配合Lambda來打印列表中的所有元素.

@FunctionalInterface
public interface Consumer {
    void accept(T t);
}

private static  void forEach(List list, Consumer consumer) {
    for (T i : list) {
        consumer.accept(i);
    }
}

// 使用Consumer
forEach(Arrays.asList("Object", "Not", "Found"), (String str) -> System.out.println(str));
forEach(Arrays.asList(1, 2, 3, 4, 5, 6), System.out::println);
Function

java.util.function.Function接口定義了一個(gè)叫做apply的方法,它接受一個(gè)泛型T的對象,并返回一個(gè)泛型R的對象。如果你需要定義一個(gè)Lambda,將輸入對象的信息映射到輸出,就可以使用這個(gè)接口(比如提取蘋果的重量,把字符串映射為它的長度)。在下面的代碼中,我們來看看如何利用它來創(chuàng)建一個(gè)map方法,將以一個(gè)String列表映射到包含每個(gè)String長度的Integer列表。

@FunctionalInterface
public interface Function {
    R apply(T t);
}

private static  List map(List list, Function function) {
    List result = new ArrayList<>();
    for (T s : list) {
        result.add(function.apply(s));
    }
    return result;
}

 List map = map(Arrays.asList("lambdas", "in", "action"), (String s) -> s.length());
// [7, 2, 6]
System.out.println(map);
原始類型特化

我們剛剛了解了三個(gè)泛型函數(shù)式接口:Predicate、Consumer和Function。還有些函數(shù)式接口專為某些類而設(shè)計(jì)。

回顧一下:Java類型要么用引用類型(比如:Byte、Integer、Object、List),要么是原始類型(比如:int、double、byte、char)。但是泛型(比如Consumer中的T)只能綁定到引用類型。這是由泛型接口內(nèi)部實(shí)現(xiàn)方式造成的。因此,在Java里面有一個(gè)將原始類型轉(zhuǎn)為對應(yīng)的引用類型的機(jī)制。這個(gè)機(jī)制叫作裝箱(boxing)。相反的操作,也就是將引用類型轉(zhuǎn)為對應(yīng)的原始類型,叫作拆箱(unboxing)。Java還有一個(gè)自動(dòng)裝箱機(jī)制來幫助程序員執(zhí)行這一任務(wù):裝箱和拆箱操作都是自動(dòng)完成的。比如,這就是為什么下面的代碼是有效的(一個(gè)int被裝箱成為Integer):

List list = new ArrayList<>;
for (int i = 0; i < 100; i++) {
    list.add(i);
}

但是像這種自動(dòng)裝箱和拆箱的操作,性能方面是要付出一些代價(jià)的。裝箱的本質(zhì)就是將原來的原始類型包起來,并保存在堆里。因此,裝箱后的值需要更多的內(nèi)存,并需要額外的內(nèi)存搜索來獲取被包裹的原始值。

Java8為我們前面所說的函數(shù)式接口帶來了一個(gè)專門的版本,以便在輸入和輸出都是原始類型時(shí),避免自動(dòng)裝箱的操作。比如,在下面的代碼中,使用IntPredicate就避免了對值1000進(jìn)行裝箱操作,但要使用Predicate就會把參數(shù)1000裝箱到一個(gè)Integer對象中:

@FunctionalInterface
public interface IntPredicate {
    boolean test(int value);
}

IntPredicate evenNumbers = (int i) -> i % 2 == 0;
// 無裝箱
evenNumbers.test(1000);

Predicate oddNumbers = (Integer i) -> i % 2 == 1;
// 裝箱
oddNumbers.test(1000);

一般來說,針對專門的輸入?yún)?shù)類型的函數(shù)式接口的名稱都要加上對應(yīng)的原始類型前綴,比如DoublePredicate、IntConsumer、LongBinaryOperator、IntFunction等。Function接口還有針對輸出參數(shù)類型變種:ToIntFunction、IntToDoubleFunction等。

Java8中還有很多常用的函數(shù)式接口,如果你有興趣可以去查找一些相關(guān)的資料,了解了這些常用的函數(shù)接口之后,會對你以后了解Stream的知識有很大的幫助。

《Java8實(shí)戰(zhàn)》這本書第三章的內(nèi)容很多,所以我打算分兩篇文章來寫。這些讀書筆記系列的文章內(nèi)容很多地方都是借鑒書中的內(nèi)容。如果您有時(shí)間、興趣和經(jīng)濟(jì)的話可以去買這本書籍。這本書我看了兩遍,是一本很不錯(cuò)的技術(shù)書籍。如果,您沒有太多的時(shí)間那么您就可以關(guān)注我的微信公眾號或者當(dāng)前的技術(shù)社區(qū)的賬號,利用空閑的時(shí)間看看我的文章,非常感謝您對我的關(guān)注!

代碼示例:

Github:chap3

Gitee: chap3

公眾號

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76688.html

相關(guān)文章

  • Java8實(shí)戰(zhàn)》-三章讀書筆記Lambda達(dá)式-02)

    摘要:上下文比如,接受它傳遞的方法的參數(shù),或者接受它的值得局部變量中表達(dá)式需要類型稱為目標(biāo)類型。但局部變量必須顯示的聲明,或?qū)嶋H上就算。換句話說,表達(dá)式只能捕獲指派給它們的局部變量一次。注捕獲實(shí)例變量可以被看作捕獲最終局部變量。 由于第三章的內(nèi)容比較多,而且為了讓大家更好的了解Lambda表達(dá)式的使用,也寫了一些相關(guān)的實(shí)例,可以在Github或者碼云上拉取讀書筆記的代碼進(jìn)行參考。 類型檢查、...

    iflove 評論0 收藏0
  • Java8實(shí)戰(zhàn)》-讀書筆記第一章(01

    摘要:依舊使用剛剛對蘋果排序的代碼。現(xiàn)在,要做的是篩選出所有的綠蘋果,也許你會這一個(gè)這樣的方法在之前,基本上都是這樣寫的,看起來也沒什么毛病。但是,現(xiàn)在又要篩選一下重量超過克的蘋果。 《Java8實(shí)戰(zhàn)》-讀書筆記第一章(01) 最近一直想寫點(diǎn)什么東西,卻不知該怎么寫,所以就寫寫關(guān)于看《Java8實(shí)戰(zhàn)》的筆記吧。 第一章內(nèi)容較多,因此打算分幾篇文章來寫。 為什么要關(guān)心Java8 自1996年J...

    codeGoogle 評論0 收藏0
  • Java8實(shí)戰(zhàn)》-讀書筆記第二章

    摘要:但是到了第二天,他突然告訴你其實(shí)我還想找出所有重量超過克的蘋果。現(xiàn)在,農(nóng)民要求需要篩選紅蘋果。那么,我們就可以根據(jù)條件創(chuàng)建一個(gè)類并且實(shí)現(xiàn)通過謂詞篩選紅蘋果并且是重蘋果酷,現(xiàn)在方法的行為已經(jīng)取決于通過對象來實(shí)現(xiàn)了。 通過行為參數(shù)化傳遞代碼 行為參數(shù)化 在《Java8實(shí)戰(zhàn)》第二章主要介紹的是通過行為參數(shù)化傳遞代碼,那么就來了解一下什么是行為參數(shù)化吧。 在軟件工程中,一個(gè)從所周知的問題就是,...

    Astrian 評論0 收藏0
  • Java8實(shí)戰(zhàn)》-第六章讀書筆記(用流收集數(shù)據(jù)-01

    摘要:收集器用作高級歸約剛剛的結(jié)論又引出了優(yōu)秀的函數(shù)式設(shè)計(jì)的另一個(gè)好處更易復(fù)合和重用。更具體地說,對流調(diào)用方法將對流中的元素觸發(fā)一個(gè)歸約操作由來參數(shù)化。另一個(gè)常見的返回單個(gè)值的歸約操作是對流中對象的一個(gè)數(shù)值字段求和。 用流收集數(shù)據(jù) 我們在前一章中學(xué)到,流可以用類似于數(shù)據(jù)庫的操作幫助你處理集合。你可以把Java 8的流看作花哨又懶惰的數(shù)據(jù)集迭代器。它們支持兩種類型的操作:中間操作(如 filt...

    EscapedDog 評論0 收藏0
  • Java8實(shí)戰(zhàn)》-第四章讀書筆記(引入流Stream)

    摘要:內(nèi)部迭代與使用迭代器顯式迭代的集合不同,流的迭代操作是在背后進(jìn)行的。流只能遍歷一次請注意,和迭代器類似,流只能遍歷一次。 流(Stream) 流是什么 流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合(通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn))。就現(xiàn)在來說,你可以把它們看成遍歷數(shù)據(jù)集的高級迭代器。此外,流還可以透明地并行處理,你無需寫任何多線程代碼了!我會在后面的筆記中...

    _ivan 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<