《Java 8 實(shí)戰(zhàn)》讀書(shū)筆記(1)—Lambda 表達(dá)式

一 前言

節(jié)前買了一本《Java8實(shí)戰(zhàn)》的書(shū),大概瀏覽了一下,其實(shí)主要講的是Java8的函數(shù)式編程,由于我們項(xiàng)目用RxJava和Scala,所以基本上了解函數(shù)式編程和命令式編程的區(qū)別。接下來(lái)幾篇博客都是以筆記的形式記錄書(shū)中內(nèi)容。
放假期間詳細(xì)看了第一部分內(nèi)容(包括前三章),主要說(shuō)的是Lambda表達(dá)式(這個(gè)是借鑒了C#,Python和Scala等語(yǔ)言的特性),引入這個(gè)就是為了語(yǔ)法的簡(jiǎn)潔。
現(xiàn)在通過(guò)書(shū)中代碼例子梳理一下幾個(gè)主要概念:行為參數(shù)化(behavior parameterization)、匿名類(Anonymous class),Lambda 表達(dá)式(Lambda expressions)、函數(shù)式接口(Functional interface)和方法引用(Method reference)等幾個(gè)重要概念。

二 項(xiàng)目需求變化

老家種了幾畝蘋(píng)果,今年大豐收,我們把這些蘋(píng)果數(shù)據(jù)信息化。

# 定義一個(gè)蘋(píng)果數(shù)據(jù)集合
List<Apple> inventory = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"));

2.1 第一個(gè)需求,篩選出綠色的蘋(píng)果

這個(gè)很好實(shí)現(xiàn),就不多說(shuō)了。

public static List<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if("green".equals(apple.getColor())){
                result.add(apple);
            }
        }
        return result;
    }

2.2 第二個(gè)需求,篩選紅色的蘋(píng)果

如果過(guò)幾天需求有變了,要篩選黃色的蘋(píng)果,不只要復(fù)制多少次代碼,果斷把顏色作為參數(shù)。

public static List<Apple> filterApplesByColor(List<Apple> inventory, String color){
        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(apple.getColor().equals(color)){
                result.add(apple);
            }
        }
        return result;
    }
# 調(diào)用
List<Apple> greenApples = filterApplesByColor(inventory, "red");

2.3 第三個(gè)需求,篩選重量大于150g的蘋(píng)果。

一般的寫(xiě)法如下

public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight){
        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(apple.getWeight() > weight){
                result.add(apple);
            }
        }
        return result;
    }
# 調(diào)用
List<Apple> heavyApples = filterApplesByWeight(inventory, 150);

2.4 第四個(gè)需求,篩選重量大于150g和紅色蘋(píng)果

同志們繼續(xù)重構(gòu),定義兩個(gè)參數(shù)

public static List<Apple> filterApples(List<Apple> inventory, String color,int weight){
        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(apple.getWeight() > weight||apple.getColor().equals(color){
                result.add(apple);
            }
        }
        return result;
    }
#調(diào)用
List<Apple> redApples = filterApples(inventory, "red",150);

三 代碼重構(gòu)

上面的需求很會(huì)變,如果客戶需要篩選形狀和產(chǎn)地時(shí),需要繼續(xù)重構(gòu)
面向接口編程,封裝行為,進(jìn)行行為參數(shù)化,其實(shí)就是策略模式。

3.1 行為參數(shù)化(behavior parameterization)

# 定義個(gè)接口(只定義一個(gè)抽象方法的接口叫函數(shù)式接口)
interface ApplePredicate{
        public boolean test(Apple a);
    }
# 實(shí)現(xiàn)過(guò)濾重量行為的類
static class AppleWeightPredicate implements ApplePredicate{
        public boolean test(Apple apple){
            return apple.getWeight() > 150; 
        }
    }
# 實(shí)現(xiàn)篩選顏色行為的類
static class AppleColorPredicate implements ApplePredicate{
        public boolean test(Apple apple){
            return "green".equals(apple.getColor());
        }
    }
# 調(diào)用
public static List<Apple> filter(List<Apple> inventory, ApplePredicate p){
        List<Apple> result = new ArrayList<>();
        for(Apple apple : inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }       

3.2 匿名類(Anonymous class)

上面的代碼還有點(diǎn)啰嗦,能不能再簡(jiǎn)單一點(diǎn),使用匿名類

List<Apple> redApples2 = filter(inventory, new ApplePredicate() {
            public boolean test(Apple a){
                return a.getColor().equals("red"); 
            }
        });

3.3 使用Lambda 表達(dá)式

java 8引入了Lambda表達(dá)式,不用像匿名類那樣,每個(gè)行為都寫(xiě)一個(gè)類模板,接下來(lái)我們繼續(xù)簡(jiǎn)化代碼。

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

3.4 使用方法引用更易讀,更自然

上面的Lambda表達(dá)式代表了直接調(diào)用類的方法,方法引用被看做針對(duì)僅僅涉及單一方法的Lambda的語(yǔ)法糖。
有三種方式構(gòu)建方法引用

  • 指向靜態(tài)方法的方法引用(例如Integer的parseInt方法,寫(xiě)作Integer::parseInt)。
  • 指向任意類型實(shí)例方法的方法引用(假設(shè)(String s)->s.toUpperCase()可以寫(xiě)作String::toUpperCase)
  • 指向現(xiàn)有對(duì)象的實(shí)例方法引用(假設(shè)你有一個(gè)局部變量Local local,用于存放Local類型對(duì)象。它有一個(gè)getValue(),則寫(xiě)法為local::getValue)
    —— Java 8實(shí)戰(zhàn)
上面代碼的簡(jiǎn)化,就是第一種構(gòu)建方式,如下:
List<Apple> greenApples = filter(inventory, String::equals);

四 Java8 常用的函數(shù)式接口

Java8中對(duì)函數(shù)式接口的描述是只定義一個(gè)抽象方法的接口叫函數(shù)式接口。

函數(shù)式接口 函數(shù)描述符 原始類型特化
Predicate<T> T >boolean IntPredicate,LongPredicate,DoublePredicate
Consumer<T> T->void IntConsumer,LongConsumer,DoubleConsumer
Function<T,R> T->R IntFunction<R>,IntToDoubleFunction ....
Supplier<T> ()->T BooleanSupplier,IntSupplier,LongSupplier
UnaryOperator<T> T->T IntUnaryOperator,LongUnaryOperator
BinaryOperator (T,T)->T IntBinaryOperator,LongBinaryOperator

參考文獻(xiàn)

[1]《Java 8實(shí)戰(zhàn)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容