溫馨提示×

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

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

Lambda表達(dá)式如何正確的在Java8中使用

發(fā)布時(shí)間:2021-01-04 14:34:00 來(lái)源:億速云 閱讀:171 作者:Leah 欄目:開發(fā)技術(shù)

這篇文章給大家介紹Lambda表達(dá)式如何正確的在Java8中使用,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

理解Lambda

Lambda表達(dá)式可以是一段可以傳遞的代碼,它的核心思想是將面向?qū)ο笾械膫鬟f數(shù)據(jù)變成傳遞行為,也就是行為參數(shù)化,將不同的行為作為參數(shù)傳入方法。

隨著函數(shù)式編程思想的引進(jìn),Lambda表達(dá)式讓可以用更加簡(jiǎn)潔流暢的代碼來(lái)代替之前冗余的Java代碼。

口說(shuō)無(wú)憑,直接上個(gè)例子吧。在Java8之前,關(guān)于線程代碼是這樣的:

class Task implements Runnable{

 @Override
 public void run() {
  System.out.println("Java8 之前 實(shí)現(xiàn)Runnable接口中的run方法");
 }
}
Runnable t = new Task();

我們定義了一個(gè)Task類,讓它實(shí)現(xiàn)Runnable接口,實(shí)現(xiàn)僅有的run方法,我們希望執(zhí)行的線程體雖然只有一句話,但我們?nèi)匀换舜罅看蟠a去定義。為了簡(jiǎn)化,我們可以采用匿名內(nèi)部類的方式:

Runnable taskBeforeJava8 = new Runnable() {
 @Override
 public void run() {
  System.out.println("Java8 之前的寫法, 傳入匿名類");
 }
};

但是,其實(shí)還是不夠簡(jiǎn)潔,我們用Lambda的寫法是這樣的:

// java8 之后
Runnable taskAfterJava8 = () -> System.out.println("Java8 之后的寫法,lambda表達(dá)式");

我們僅僅使用()->就完成了這件事,是不是非常簡(jiǎn)潔呢?如果你覺(jué)得雖然Lambda寫法簡(jiǎn)潔,但是它的規(guī)則讓人摸不著頭腦,那就跟著我接下去學(xué)叭。

基礎(chǔ)語(yǔ)法

(parameters) -> action
 (parameters) -> expression
 (parameters) -> {statements;}

parameters代表變量,可以為空,可以為單,可以為空,你能想到的方式他都可以。

action是實(shí)現(xiàn)的代碼邏輯部分,可以是一行代碼expression,也可以是一個(gè)代碼片段statements。如果是代碼片段,需要加上{}。

下面是一些合法的示例,你可以看看有沒(méi)有掌握:


表達(dá)式描述
() -> 1024不需要參數(shù),返回值為1024
x -> 2 * x接收參數(shù)x,返回其兩倍
(x, y) -> x - y接收兩個(gè)參數(shù),返回它們的差
(int x, int y) -> x + y接收兩個(gè)int類型參數(shù),返回他們的和
(String s) -> print(s)接收一個(gè)String對(duì)象,并打印

函數(shù)式接口

@FunctionalInterface // 此注解作用的接口 只能擁有一個(gè)抽象方法
public interface Runnable {
 public abstract void run();
}

在這里,@FunctionalInterface注解是非必須的,有點(diǎn)類似于@Override,起強(qiáng)調(diào)作用,如果你的接口標(biāo)注該注解,卻沒(méi)有遵循它的原則,編譯器會(huì)提示你修改。

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

JDK原生為我們提供了一些常用的函數(shù)式編程接口,讓我們?cè)谑褂盟麄兙幊虝r(shí),不必關(guān)心接口名,方法名,參數(shù)名,只需關(guān)注它的參數(shù)類型,參數(shù)個(gè)數(shù),返回值。


接口參數(shù)返回值類別示例
ConsumerTvoid消費(fèi)型接口打印輸出某個(gè)值
SupplierNoneT供給型接口工廠方法獲取一個(gè)對(duì)象
FunctionTR函數(shù)型接口獲取傳入列表的總和
PredicateTboolean斷言型接口判斷是否以summer為前綴

消費(fèi)型接口

@FunctionalInterface // 此注解作用的接口 只能擁有一個(gè)抽象方法
public interface Runnable {
 public abstract void run();
}

供給型接口

/**
  * 供給型接口, 無(wú)參數(shù),返回T
  */
 public static void supplierTest() {
  Supplier<Object> supplier = () -> new Object();
  System.out.println(supplier.get());
 }

斷言型接口

 /**
  * 斷言型 傳入?yún)?shù)T ,返回boolean
  */
 public static void predicateTest() {
  Predicate<String> predicate = name -> name.startsWith("summer");
  System.out.println(predicate.test("summerday"));
 }

函數(shù)型接口

 /**
  * 函數(shù)型接口 傳入T 返回R
  */
 public static void functionTest() {
  List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
  Function<List<Integer>, Integer> function = num -> {
   int res = 0;
   for (int n : list) {
    res += n;
   }
   return res;
  };
  Integer num = function.apply(list);
  System.out.println(num);
 }

方法引用

方法引用可以看作特定Lambda表達(dá)式的快捷寫法,主要分為以下兩種:

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

  • 指向現(xiàn)有對(duì)象的實(shí)例方法的方法引用

/**
 * 方法引用
 * 1. 指向靜態(tài)方法的方法引用
 * 2. 指向現(xiàn)有對(duì)象的實(shí)例方法的方法引用
 *
 * @author Summerday
 */
public class MethodReferenceTest {
	
 public static List<String> getList(List<String> params, Predicate<String> filter) {
  List<String> res = new LinkedList<>();
  for (String param : params) {
   if (filter.test(param)) {
    res.add(param);
   }
  }
  return res;
 }
 // 靜態(tài)方法
 public static boolean isStartWith(String name) {
  return name.startsWith("sum");
 }

 public static void main(String[] args) {
  List<String> params = Arrays.asList("summerday","tqbx","天喬巴夏","summer","");
  //靜態(tài)方法的方法引用 getList(params, name -> MethodReferenceTest.isStartWith(name));
  List<String> list = getList(params, MethodReferenceTest::isStartWith);
  System.out.println(list);
  
  // 指向現(xiàn)有對(duì)象的實(shí)例方法的方法引用 getList(params, name -> name.isEmpty());
  List<String> sum = getList(params, String::isEmpty);
  System.out.println(sum);
  
 }
}

數(shù)組引用

/**
 * 數(shù)組引用
 * @author Summerday
 */
public class ArrayReferenceTest {

 public static void main(String[] args) {
  // 普通lambda
  Function<Integer,String[]> fun1 = x -> new String[x];
  String[] res1 = fun1.apply(10);
  System.out.println(res1.length);

  // 數(shù)組引用寫法
  Function<Integer,String[]> fun2 = String[]::new;
  String[] res2 = fun2.apply(10);
  System.out.println(res2.length);

 }
}

構(gòu)造器引用

/**
 * 構(gòu)造器引用
 * @author Summerday
 */
public class ConstructorReferenceTest {

 public static void main(String[] args) {

  // 普通lambda
  Supplier<User> sup = () -> new User();

  // 構(gòu)造器引用
  Supplier<User> supplier = User::new;
  User user = supplier.get();
  System.out.println(user);
 }

}

class User{

}

總結(jié)

  •  lambda表達(dá)式?jīng)]有名稱,但有參數(shù)列表,函數(shù)主體,返回類型,可能還有一個(gè)可以拋出的異常的列表。

  • lamda表達(dá)式讓你可以將不同的行為作為參數(shù)傳入方法。

  • 函數(shù)式接口是僅僅聲明了一個(gè)抽象方法的接口。只有在接受函數(shù)式接口的地方才可以使用lambda表達(dá)式。

  • lambda表達(dá)式允許你直接內(nèi)聯(lián),為函數(shù)式接口的抽象方法提供實(shí)現(xiàn),并將整個(gè)表達(dá)式作為函數(shù)式接口的一個(gè)實(shí)例。

  • Java8自帶了一些常用的函數(shù)式接口,包括Predicate,Function,Supplier,Consumer,BinaryOperator

  • 方法引用讓你重復(fù)使用現(xiàn)有的方法實(shí)現(xiàn)并直接傳遞他們:Classname::method。

關(guān)于Lambda表達(dá)式如何正確的在Java8中使用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

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

AI