溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java8中Lambda的特性是什么

發(fā)布時間:2021-06-30 17:48:48 來源:億速云 閱讀:137 作者:Leah 欄目:編程語言

Java8中Lambda的特性是什么,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

lambda快速體驗

入門最快就是看demo啦,現(xiàn)在有個需求,讓你在眾多蘋果中挑選出紅色的蘋果

  • 蘋果類

public class Apple {
    String color;
    int weight;
	//省略構(gòu)造函數(shù),get方法
}
寫法1:
public static List<Apple> filterGreenAppleWithNormal(List<Apple> apples) {
    List<Apple> res = new ArrayList<>();
    for (Apple apple : apples) {
        if ("red".equals(apple.getColor())) {
            res.add(apple);
        }
    }
    return res;
}

//調(diào)用
List<Apple> normal = filterGreenAppleWithNormal(apples);

如果再有一個需求說挑選出綠色的蘋果呢,按照這種寫法就需要創(chuàng)建一個新的類,然后僅僅把"red" 修改成"green" 其它都不變,這明顯是不顯示的。所以可以把顏色當成參數(shù)傳進去

寫法2:
public static List<Apple> filterGreenAppleWithArg(List<Apple> apples, String color) {
    List<Apple> res = new ArrayList<>();
    for (Apple apple : apples) {
        if (color.equals(apple.getColor())) {
            res.add(apple);
        }
    }
    return res;
}

//調(diào)用
List<Apple> arg = filterGreenAppleWithArg(apples, "red");

此時再有一個需求,需要篩選出一定重量或者某個顏色的蘋果,需要怎么辦呢,按照上述想法是把能想到的屬性都堆到方法的參數(shù)中。

public static List<Apple> filterWeightOrColorWithArg(List<Apple> apples, String color, int weight, boolean flag) {
    List<Apple> res = new ArrayList<>();

    for (Apple apple : apples) {
        if (flag && color.equals(apple.getColor()) || !flag && apple.getWeight() > weight) {
            res.add(apple);
        }
    }
    return res;
}

//調(diào)用
List<Apple> weightOrColor = filterWeightOrColorWithArg(apples, "", 500, false);

可以這樣寫嗎,當然可以解決問題,但是如果有5個屬性呢,6個屬性呢,還有,參數(shù)中的flag是什么意思呢。

仔細一想,篩選顏色,篩選重量,這些的本質(zhì)是在篩選,是一個行為(后面更專業(yè)稱謂語),可以把行為抽象成一個接口 。

  • 行為接口

public interface AppleFilter {
    boolean filter(Apple apple);
}
寫法3:

首先需要實現(xiàn)這個接口來具體化行為

  • 篩選紅色蘋果實現(xiàn)類

public class RedFilter implements AppleFilter {
    @Override
    public boolean filter(Apple apple) {
        return "red".equals(apple.getColor());
    }
}

回到使用

public static List<Apple> filterApples(List<Apple> apples, AppleFilter filter) {
    List<Apple> res = new ArrayList<>();

    for (Apple apple : apples) {
        if (filter.filter(apple)) {
            res.add(apple);
        }
    }

    return res;
}

//調(diào)用
List<Apple> behavior = filterApples(apples, new GreenFilter());

這樣看就舒服多了,當有新需求的時候,只需要再添加一個類,比如需求是篩選出重量超200g的蘋果,只需要新建一個篩選類實現(xiàn)上述接口即可。

public class WeightGt200Filter implements AppleFilter {
    @Override
    public boolean filter(Apple apple) {
        return apple.getWeight() > 200;
    }
}

還能怎樣精簡代碼呢?熟悉Java的小伙伴到這里應(yīng)該就想到了匿名內(nèi)部類

寫法4:
List<Apple> innerClass = filterApples(apples, new AppleFilter() {
    @Override
    public boolean filter(Apple apple) {
        return "green".equals(apple.getColor());
    }
});

一般到這一步,比較不錯的IDE就會開始提醒建議了

Java8中Lambda的特性是什么

這就到了我們今天的重點,lambda表達式

寫法5:
List<Apple> lambda = filterApples(apples, apple -> apple.getWeight() > 500);

沒錯,就是這么精簡,不過filterApples 這個方法是不能省略的,但是擴展性相較1,2,簡潔性相較3,4都好了很多

什么是lambda

可以把Lamdba表達式理解為簡潔地表示可傳遞的匿名函數(shù)的一種形式:它沒有名稱,但它有參數(shù)列表、函數(shù)主題、返回類型,可能還有一個可以拋出的異常列表

書寫格式: (參數(shù)) -> {主體}

正如上面寫法5一樣(apple) -> {apple.getWeight() > 500;}

  • lambda表達式對參數(shù)能夠自動推斷類型,當然也可以顯示書寫類型

  • 沒有return語句,應(yīng)為已經(jīng)有隱含了return

  • lambda中可以有多行語句

使用案例:

  • () -> {}

  • () -> "java"

  • () -> {return "java";}

  • (int a, int b) -> a * b

  • () -> {System.out.println("hello"); System.out.println("java");}

如何才能使用lambda

使用函數(shù)式接口的時候才能使用lambda表達式

所謂函數(shù)式接口就是僅僅定義了一個抽象方法,比如一開始把行為抽象成一個AppleFilter 接口,該接口只有一個filter() 方法。注意是只有一個抽象方法,并不是只有一個方法,通俗來說是繼承該接口的類只需要實現(xiàn)一個方法。

最常見的兩個接口是ComparatorRunnable

Java8中Lambda的特性是什么

后來為了更方便地區(qū)分函數(shù)式接口,Java新的API中多了一個@FuntionalInterface ,該注解僅僅是表明該類是函數(shù)式接口(并不是必須的),如果有該注解的同時聲明了兩個抽象方法,那么將會報錯

Java8中Lambda的特性是什么

java.util.function下4個常用的函數(shù)式接口

java.util.function 下主要有4個常用的函數(shù)式接口,Function,Predicate,Consumer,Predicate ,隨便截取其中的一個源碼片段來看,其實也沒啥好看的

Java8中Lambda的特性是什么

對這些函數(shù)式接口也是得看接口是如何聲明的,這里就拿Predicate 舉例,該接口主要是對傳進來的對象進行一個處理,然后返回boolean 值。是不是有點熟悉,沒錯,就是和篩選蘋果一樣

  • predicateDemo

public static List<Apple> predicateDemo(List<Apple> apples, Predicate<Apple> predicate) {
    List<Apple> res = new ArrayList<>();
    for (Apple apple : apples) {
        if (predicate.test(apple)) {
            res.add(apple);
        }
    }
    return res;
}

//調(diào)用
List<Apple> predicate = predicateDemo(apples, apple -> "green".equals(apple.getColor()));

其他的也是同理,上才藝

  • functionDemo

public static List<Integer> functionDemo(List<Integer> nums, Function<Integer, Integer> function) {
    List<Integer> res = new ArrayList<>();
    for (int num : nums) {
        res.add(function.apply(num));
    }
    return res;
}

//調(diào)用
List<Integer> function = functionDemo(Arrays.asList(1, 8, 7, 3, 9, 2), (num) -> num * 2);
  • consumerDemo

public static void consumerDemo(List<Integer> list, Consumer<Integer> consumer) {
    for (int num : list) {
        consumer.accept(num);
    }
}

//調(diào)用
consumerDemo(Arrays.asList(1, 5, 6), (num) -> System.out.println(num));
consumerDemo(Arrays.asList(1, 5, 6), System.out::println);
  • supplierDemo

public static void supplierDemo(List<Integer> nums, Supplier<String> supplier) {
    StringBuilder sb = new StringBuilder();
    for (int num : nums) {
        sb.append(num).append(supplier.get());
    }
    System.out.println(sb);
}

//調(diào)用
supplierDemo(Arrays.asList(1, 5, 6), ()->"java");

方法引用

上面的lambda寫法是最精簡的嗎,不,不是的,還有最最最精簡的寫法,那就是利用方法引用

方法引用主要有3類:

  • 指向靜態(tài)方法的方法引用

Comparator<Integer> normalComparator = (a, b) -> a.compareTo(b);
Comparator<Integer> referenceComparator = Integer::compareTo;
  • 指向任一類型實例方法的方法引用

Function<String, Integer> normalFunction = (str) -> str.length();
Function<String, Integer> referenceFunction = String::length;

BiPredicate<List<String>, String> normalPredicate = (strings, str) -> strings.contains(str);
BiPredicate<List<String>, String> referencePredicate = List::contains;
  • 指向現(xiàn)有對象的實例方法引用

Apple apple = new Apple();
Supplier<Integer> normal = () -> apple.getWeight();
Supplier<Integer> reference = apple::getWeight;
  • 當然也可以用于構(gòu)造函數(shù)

Supplier<Apple> normalSupplier = () -> new Apple();
Supplier<Apple> referenceSupplier = Apple::new;

看完上述內(nèi)容,你們掌握Java8中Lambda的特性是什么的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI