行為參數化與lambda運算式 - 讀《Java 8實戰》

來源:互聯網
上載者:User

標籤:list   ide   1.5   method   lint   stat   none   com   one   

零、 概述

第一部分:1~3章 主要講了行為參數化和Lambda運算式

第二部分:4~7章 主要講了流的應用,包括流與集合差異,流的操作,收集器,注的並存執行

第三部分:8~12章 主要講了怎樣用Java8引入的特性改善老代碼,Optional類和CompleteFuture及新的日期和時間API

第四部分:13~16章 主要講了函數式編程

本文主要是對第一部分的筆記。

一、行為參數化1.1 行為參數化定義

行為參數化就是拿出一個代碼塊,把它準備好卻不去執行它。

1.2 舉例:需求

有個果農,有如下需求:

  1. 從倉庫中找到紅色蘋果
  2. 找出所有重量超過150g的

擴充一下:

  1. 可能以後還需要尋找綠色蘋果的功能
  2. 可能還需要找重量超過200g的
1.3 舉例:方案1

傳統實現方案

// 篩選綠色蘋果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;}// 可篩選任意顏色蘋果,把顏色作為參數public static List<Apple> filterGreenApplesByColor(List<Apple> inventory, String color) {    List<Apple> result = new ArrayList<>();    for (Apple apple : inventory) {        if (apple.getColor().equals(apple.getColor())) {            result.add(apple);        }    }    return result;}// 篩選不同重量的蘋果public static List<Apple> filterGreenApplesByWeight(List<Apple> inventory, int weight) {    List<Apple> result = new ArrayList<>();    for (Apple apple : inventory) {        if (apple.getWeight() > weight) {            result.add(apple);        }    }    return result;}// 寫一個方法同時支援篩選顏色和重量public static List<Apple> filterGreenApples(List<Apple> inventory, String color, int weight            , boolean filterColorFlag) {    List<Apple> result = new ArrayList<>();    for (Apple apple : inventory) {        if ((filterColorFlag && apple.getColor().equals(color))                || (!filterColorFlag && apple.getWeight() > weight)) {            result.add(apple);        }    }    return result;}
1.4 舉例:方案2

使用對象傳遞行為參數

interface ApplePredicate {    // 一個返回boolea值的函數,把它稱為謂詞    boolean test(Apple apple);}// 篩選綠色public class AppleGreenColorPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        return "green".equals(apple.getColor());    }}// 重量大於150class AppleHeavyWeightPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        return apple.getWeight() > 150;    }}// 紅色且重量大於150class AppleRedAndHeavyPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        return "red".equals(apple.getColor()) && apple.getWeight() > 150;    }}// 實現public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {    List<Apple> result = new ArrayList<>();    for (Apple apple : inventory) {        if (p.test(apple)) {            result.add(apple);        }    }    return result;}public void test() {    List<Apple> inventory = new ArrayList<>();    // 篩選綠色    filterApples(inventory, new AppleGreenColorPredicate());    // 重量大於150    filterApples(inventory, new AppleHeavyWeightPredicate());    // 紅色且重量大於150    filterApples(inventory, new AppleRedAndHeavyPredicate());}
1.5 舉例:方案3

使用匿名類傳遞行為參數

// 對選擇標準建模interface ApplePredicate {    // 一個返回boolea值的函數,把它稱為謂詞    boolean test(Apple apple);}// 實現public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {    List<Apple> result = new ArrayList<>();    for (Apple apple : inventory) {        if (p.test(apple)) {            result.add(apple);        }    }    return result;}public static void main(String[] args) {    List<Apple> inventory = new ArrayList<>();    // 篩選綠色    filterApples(inventory, new ApplePredicate() {        @Override        public boolean test (Apple apple){            return "green".equals(apple.getColor());        }    });    // 重量大於150    filterApples(inventory, new ApplePredicate() {        @Override        public boolean test (Apple apple){            return apple.getWeight() > 150;        }    });    // 紅色且重量大於150    filterApples(inventory, new ApplePredicate() {        @Override        public boolean test (Apple apple){            return "red".equals(apple.getColor()) && apple.getWeight() > 150;        }    });}
1.6 舉例:方案4

使用Lambda運算式傳遞行為參數

interface ApplePredicate {    boolean test(Apple apple);}public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {    List<Apple> result = new ArrayList<>();    for (Apple apple : inventory) {        if (p.test(apple)) {            result.add(apple);        }    }    return result;}public static void main(String[] args) {    List<Apple> inventory = new ArrayList<>();    // 篩選綠色    filterApples(inventory        , (Apple apple) -> "green".equals(apple.getColor()));    // 重量大於150    filterApples(inventory        , (Apple apple) -> apple.getWeight() > 150);    // 紅色且重量大於150    filterApples(inventory        , (Apple apple) -> "red".equals(apple.getColor()) && apple.getWeight() > 150);}

在這裡小結一下:

1.7 舉例:方案5

在方案4的基礎上 將List類型抽象化

// 定義一個函數式介面interface Predicate<T> {    boolean test(T t);}// 定義一個調用函數式介面的方法public static <T> List<T> filter(List<T> list, Predicate<T> p) {    List<T> result = new ArrayList<>();    for (T e : list) {        if (p.test(e)) {            result.add(e);        }    }    return result;}// 使用public static void main(String[] args) {    List<Apple> inventory = FakeDb.getApples();    List<Apple> redList = Filtering.filter(inventory        , (Apple apple) -> "red".equals(apple.getColor()));    List<String> nonEmptyList = filter(Arrays.asList("1", "", "2")        , (String s) -> !s.isEmpty());}
二、Lambda運算式2.1 Lambda運算式定義

簡潔地表示可傳遞的匿名函數的一種方法。

  • 匿名 {:&.fadeIn}
  • 函數
  • 傳遞
  • 簡潔
2.2 Lambda運算式長什麼樣子?

下面是5個有效Lambda運算式

// 1 參數是String s,傳回值是int(String s) -> s.length()// 2 參數是Apple a,傳回值是boolean(Apple a) -> a.getWeight() > 150//  3 參數是int x,int y 沒有傳回值 {}內放語句,怎樣區分語句與運算式(int x, int y) -> {    System.out.println("Result:");    System.out.println(x + y);}// 4 無參數,返回int() -> 42// 5 參數是兩個Apple類型的變數,傳回值是boolean(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())
2.3 函數式介面

函數式介面就是只定義一個抽象方法的介面。

函數式介面的抽象方法的簽名基本上就是Lambda運算式的簽名,這種抽象方法叫做函數描述符

一個註解:@FunctionalInterface,不是必須的,用於表示該介面會設計成一個函數式介面

2.4 Lambda的使用

Predicate 過濾掉列表中的空串

// 定義一個函數式介面interface Predicate<T> {    boolean test(T t);}// 定義一個調用函數式介面的方法public static <T> List<T> filter(List<T> list, Predicate<T> p) {    List<T> result = new ArrayList<>();    for (T e : list) {        if (p.test(e)) {            result.add(e);        }    }    return result;}// 使用public static void main(String[] args) {    List<String> nonEmptyList = filter(Arrays.asList("1", "", "2")        , (String s) -> !s.isEmpty());}

Consumer 計算資料行表中的每個元素的平方並輸出

@FunctionalInterfacepublic 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);    }}public static void main(String[] args) {    forEach(Arrays.asList(1, 2, 3, 4), (Integer i) -> System.out.println(i * i));}

Function** 返回列表中每個元素的長度

@FunctionalInterfacepublic 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;}public static void main(String[] args) {    List<Integer> result = map(Arrays.asList("1", "22", "333")        , (String s) -> s.length());}

2.5 類型推斷
List<Apple> l = new ArrayList<Apple>();List<Apple> l = new ArrayList<>();// Java編譯器根據Lambda出現的上下文來推斷Lambda運算式參數的類型Predicate<Apple> p = (Apple a) -> 'red'.equals(a.getColor())Predicate<Apple> p = a -> 'red'.equals(a.getColor())
2.6 方法引用

主要為了簡化代碼

方法引用,3種

  • 指向靜態方法的方法引用 String.parseInt()
  • 指向執行個體方法的方法引用 str.length()
  • 指向外部對象執行個體方法的方法引用 globalVar.instanceMethod()
List<String> strList = Arrays.asList("a", "b", "A", "B");strList.sort((s1, s2) -> s1.compareToIgnoreCase(s2));strList.sort(String::compareToIgnoreCase); // 等效的方法引用

建構函式引用

Supplier<Apple> c1 = Apple::new; // 指向Apply()建構函式Apple a1 = c1.get();Function<Integer, Apple> c2 = Apple::new; // 指向Apply(int weight)建構函式Apple a2 = c2.apply(110);BigFunction<String, Integer, Apple> c3 = Apple::new;// 指向Apply(String color, Integer weight)Apple c3 = c3.apply("green", 110);
2.7 Lambda實戰

根據Apple的重量來排序

// 行為參數化,下面是通過不同方式傳遞這個行為的// 1.使用對象public class AppleComparator implements Comparator<Apple> {    public int compare(Apple a1, Apple a2) {        return a1.getWeight().compareTo(a2.getWeight());    }}inventory.sort(new AppleComparator());// 2.使用匿名類inventory.sort(new Comparator<Apple>(){    public int compare(Apple a1, Apple a2) {        return a1.getWeight().compareTo(a2.getWeight());    }});    // 3.使用Lambda運算式inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));// 因為類型推斷,可以簡化成inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));// 因為有個java.util.Comparator.comparing靜態方法,還可以簡化成import static java.util.Comparator.comparing;inventory.sort(comparing((a) -> a.getWeight()));// 4.使用方法引用inventory.sort(comparing(comparing(Apple::getWeight)));
2.8 複合Lambda運算式

比較子複合

// 逆序,蘋果按重量遞減排序inventory.sort(comparing(Apple::getWeight).reversed());// 比較子鏈,先按重量遞減排序再按國家排序inverntory.sort(comparing(Apple::getWeight).reversed()               .thenComparing(Apple::getCountry));

謂詞複合

// negate,and,or// 篩選不是紅蘋果Predicate<Apple> notRedApple = redApple.negate();// 篩選紅蘋果且重量大於150   或  綠蘋果redApple.and(a -> a.getWeight() > 150).or(a -> "green".equals(a.getColor()));// a.or(b).and(c) <==> (a || b) && c

函數複合

// andThen,composeFunction<Integer, Integer> f = x -> x + 1;Function<Integer, Integer> g = x -> x * 2;// g(f(x))Function<Integer, Integer> h = f.andThen(g);int result = h.apply(1);// f(g(x))Function<Integer, Integer> h = f.compose(g);int result = h.apply(1);
三、代碼

https://gitee.com/yysue/tutorials-java/tree/master/java-8

行為參數化與lambda運算式 - 讀《Java 8實戰》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.