中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

Java的Lambda表達式使用實例分析

發布時間:2023-04-07 11:35:31 來源:億速云 閱讀:146 作者:iii 欄目:開發技術

這篇文章主要講解了“Java的Lambda表達式使用實例分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java的Lambda表達式使用實例分析”吧!

Lambada 簡介

lambda 表達式 是Java 8新加入的新特性,它在Java中是引入了函數式編程這一概念。那么什么是函數式編程呢?

函數式編程:函數式編程是面向數學的抽象,將計算描述為一種表達式求值。

我們平常所說的面向對象編程屬于命令式編程,函數式編程和命令式編程的區別是:

  • 函數式編程關心數據的映射,命令式編程關系解決問題的步驟。

  • 函數式編程關系類型(代數結構)之間的關系,命令式編程關系解決問題的步驟。

函數式編程的本質:

函數式編程中的函數指的不是計算機中的函數,而是數學中的函數,即自變量的映射。即:一個函數的值僅取決于函數參數的值,不依賴其他狀態。

嚴格意義上的函數式編程意味著不使用可變的變量,賦值,循環和其他命令式控制結構進行編程。

函數式編程的好處:

函數式編程的好處是主要是不可變性帶來的。沒有可變的狀態,函數就是引用透明(Referential transparency)的和沒有副作用的(No Side Effect)。

上面這些都是一些基本的概念,但是我們平時可能接觸這些方面的東西比較少,所以一開始感覺函數式編程是很難得東西。

簡單的示例

Talk is cheap, show me the code!

先來一個最簡單的例子,可能也是介紹的最多的例子了。哈哈!

給按鈕添加監視器。

使用匿名內部類的方式,進行添加。

submit.addActionListener(new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent e) {
		JOptionPane.showMessageDialog(null, "點擊了確定按鈕", "確定", JOptionPane.INFORMATION_MESSAGE);
	}
});

這種方式的缺點:使用了很多的模板代碼,真正必要的代碼,只是方法體內的代碼。所以,Java 8 引入的 Lambda 表達式可以簡化這種代碼(當然了,也是有限制的,不是所有的匿名內部類都可以,這個后面會提到。)。

使用 Lambda 表達式 簡化代碼

submit.addActionListener((e)->{
		JOptionPane.showMessageDialog(null, "點擊了確定按鈕", "確定", JOptionPane.INFORMATION_MESSAGE);
});

Lambda 表達式是一個匿名方法,將行為像數據一樣進行傳遞。

說明

可以看出來,使用 Lambda 表達式簡化后的代碼表達變得更加清晰了,并且不用再去寫繁瑣的模板代碼了。

進一步簡化

參數括號和代碼體的花括號也可以省略(只有一個參數時,可以省略圓括號,只有一行代碼時,可以省略花括號)。

ActionListener listener = e->JOptionPane.showMessageDialog(null, "點擊了確定按鈕", "確定", JOptionPane.INFORMATION_MESSAGE);

小結
當使用 Lambda 表達式代替匿名內部類創建對象時,Lambda 表達式的代碼塊將會替代實現抽象方法的方法體,Lambda 就相當于一個匿名方法。

Lambda 表達式的組成部分

lambda 表達式由三部分組成:

  • 形參列表。形參列表允許省略形參類型。如果形參列表中只有一個參數,可以省略形參列表的圓括號。

  • 箭頭(->)。英文短線和大于號。

  • 代碼塊。如果代碼塊只有一句,可以省略花括號。如果只有一條 return 語句,可以省略 return,lambda表達式會自動返回這條語句的值。

注:
之所以可以省略形參列表是因為 編譯器 可以進行類型推斷,例如:

List<Dog> dogs1 = new ArrayList<Dog>();

List<Dog> dogs2 = new ArrayList<>();

上面使用 菱形語法,可以省略尖括號里面的東西,這就是類型推斷的作用
但是類型推斷也不是萬能的,不是所有的都可以推斷出來的,所以有時候,還是要顯示的添加形參類型,例如:

先不要管這個代碼的具體作用。

BinaryOperator b = (x, y)->x*y;
//上面這句代碼無法通過編譯,下面是報錯信息:無法將 * 運算符作用于 java.lang.Object 類型。
The operator * is undefined for the argument type(s) java.lang.Object, java.lang.Object
//添加參數類型,正確的代碼。
BinaryOperator<Integer> b = (x, y)->x*y;

所以,類型推斷不是萬能的,如果編譯器無法推斷,那就是我們的錯誤,不要過度依賴編譯器。有時候,顯示的添加參數類型,還是很必要的,當然了,這需要去多練習。

函數式接口

前面了解了,Lambda 表達式可以代替匿名內部類,進而達到簡化代碼,表達清晰的目的。那么使用 Lambda 表示式的前提是什么呢?-- 函數式接口

Lambda 表達式的類型,也被稱為 目標類型 (Target Type),它必須是一個函數式接口(Functional Interface)。所謂函數式接口,指的就是:只包含一個抽象方法的接口。(可以包含多個默認方法,靜態方法,但必須只有一個抽象方法)。
注:Java 8 專門提供了一個注解:@FunctionalInterface。用于標注某個接口是函數式接口,這樣編譯時就會檢查,如果該接口含有多個抽象方法,編譯器就會報錯。

上面使用 Lambda 表達式來為按鈕添加了監視器,可以看出來,Lambda 表達式 代替了 new ActionListener()對象。

所以 Lambda 的表達式就是被當成一個對象。

例如:

ActionListener listener = e->JOptionPane.showMessageDialog(null, "點擊了確定按鈕", "確定", JOptionPane.INFORMATION_MESSAGE);

從上面這個例子中可以看出來,Lambda 表達式實現的是匿名方法&ndash;因此它只能實現特定函數式接口中的唯一方法。
所以 Lambda 表達式有下面兩種限制:

Lambda 表達式的目標類型必須是明確的函數式接口。 Lambda 表達式只能為函數式接口創建對象。Lambda只能實現一個方法,因此它只能為含有一個抽象方法的接口(函數式接口)創建對象。 介紹幾個 Java 中重要的函數接口

Java的Lambda表達式使用實例分析

從這種表可以看出來,抽象方法的名字反而不是最重要的了,重要的是參數和返回值。 因為在寫 Lambda 表達式的時候,也不要使用 抽象方法名了。

上面使用幾個簡單的例子來說明上面接口的應用:

測試代碼

import java.text.ParseException;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;

public class Test {
	public static void main(String[] args) throws ParseException {
		//Lambda 表達式中的構造器引用,用于簡化代碼。
		Creat<Dog> c = Dog::new;
		Dog dog = c.creat("小黑", 15);
		System.out.println(dog.toString());
		
		Predicate<String> predicate = (words)->{
			return words.length() > 20;
		};
		assert predicate.test("I love you yesterday and today!") : "長度小于20";
		assert !predicate.test("God bless you!") : "長度小于20";
		System.out.println("------------------------");
		
		Consumer<Dog> consumer = System.out::println;
		consumer.accept(dog);
		System.out.println("------------------------");

		Function<Dog, String> function = (dogObj)->{
			return dogObj.getName();
		};
		System.out.println(function.apply(dog));
		System.out.println("------------------------");
		
		Supplier<Dog> supplier = ()->{
			return new Dog("大黃", 4);
		};
		System.out.println(supplier.get());
		
		//一元操作符
		UnaryOperator<Boolean> unaryOperation = (flag)->{
			return !flag;
		};
		System.out.println(unaryOperation.apply(true));
		
		BinaryOperator<Integer> binaryOperator = (x, y)->x*y;
		int result = binaryOperator.apply(999, 9999);
		System.out.println(result);
	}
}

測試使用的實體類

public class Dog {
	private String name;
	private int age;
	
	public Dog(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Dog [name=" + name + ", age=" + age + "]";
	}
}

自定義函數式接口

@FunctionalInterface
public interface Creat<T> {
	public T creat(String name, int age);
}

運行截圖就不放了,感興趣的可以試一下。

說明
我這里直接使用 Lambda 創建了對象,然后調用了這個對象的方法(就是lambda 的代碼塊部分),真正使用的時候,都是直接傳遞 Lambda 表達式的,這種方法并不推薦,但是可以讓我們很好的理解為什么? 可以看出來,Lambda 表達式的作用,最后還是需要調用 重寫的抽象方法的,只不過使用表達更加清晰,簡化了代碼。

例如:

		List<Dog> dogs = new ArrayList<>();
		dogs.add(new Dog("大黃", 2));
		dogs.add(new Dog("小黑", 3));
		dogs.add(new Dog("小哈",1));
		//將行為像數據一樣傳遞,使用集合的 forEach 方法來遍歷集合,
		//參數可以是一個 Lambda 表達式。
		Consumer<? super Dog> con = (e)->{
			System.out.println(e);
		};
		dogs.forEach(con);
		System.out.println("--------------------------\n");
	
		//直接傳遞 Lambda 表達式,更加簡潔
		dogs.forEach(e->System.out.println(e));
		System.out.println("--------------------------\n");

		//使用方法引用,進一步簡化(可以看我的另一篇關于方法引用的博客)
		dogs.forEach(System.out::println);
		System.out.println("--------------------------\n");

		//使用 Lambda 對集合進行定制排序,按照年齡排序(從小到大)。
		dogs.sort((e1, e2)->e1.getAge()-e2.getAge());
		dogs.forEach(System.out::println);

可以看出來,通過使用 Lambda 表達式可以,極大的簡化代碼,更加方便的操作集合。值得一提的是:Lambda 表達式 和 Stream 的結合,可以擁有更加豐富的操作,這也是下一步學習的方向。

運行截圖:

Java的Lambda表達式使用實例分析

感謝各位的閱讀,以上就是“Java的Lambda表達式使用實例分析”的內容了,經過本文的學習后,相信大家對Java的Lambda表達式使用實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

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

AI

体育| 太原市| 博爱县| 青田县| 永嘉县| 温州市| 抚宁县| 中江县| 博爱县| 马公市| 揭阳市| 屏东市| 武宁县| 田林县| 新闻| 兰西县| 安西县| 东辽县| 华亭县| 闵行区| 蒙山县| 加查县| 安塞县| 都兰县| 财经| 西吉县| 桑日县| 堆龙德庆县| 鹤庆县| 油尖旺区| 西畴县| 册亨县| 丰城市| 望江县| 台北市| 宜宾市| 吉林省| 新和县| 木兰县| 库尔勒市| 栖霞市|