【Java進階】Java Lambda 表達式、Stream API完整梳理

一、Lambda表達式

Lambda 表達式是一種匿名函數,它可以用來定義函數式接口的實現。Lambda 表達式可以用來簡化代碼,提高代碼的可讀性和可維護性。

1、Lambda 表達式

1.1、語法介紹

Lambda 表達式的語法如下:

(parameters) -> expression or statement或者(parameters) -> { statements; }

Lambda表達式由以下幾個部分組成:

  • 參數列表(parameters):Lambda表達式可以有零個或多個參數。如果有多個參數,使用逗號將它們分隔開。參數的類型可以顯式指定,也可以通過上下文推斷得出。

  • 箭頭符號(->):箭頭符號用于分隔參數列表和Lambda表達式的主體。

  • 表達式(expression)或語句塊(statements):Lambda表達式的主體可以是一個表達式或一個代碼塊。如果主體是一個表達式,則可以直接返回該表達式的結果。如果主體是一個代碼塊,則需要使用大括號將代碼塊括起來,并且可能需要使用return語句來返回結果。

Lambda 表達式是一種匿名函數,它可以用來定義函數式接口的實現。Lambda 表達式可以用來簡化代碼,提高代碼的可讀性和可維護性。

1.2、Lambda表達式特性

除了Java版本的要求外,Lambda表達式只能用于函數式接口。

  1. 函數式接口:Lambda表達式只能用于函數式接口,即只有一個抽象方法的接口。函數式接口可以使用@FunctionalInterface注解進行標記,以確保只有一個抽象方法。
@FunctionalInterface
interface MyInterface {void myMethod();
}public class Main {public static void main(String[] args) {MyInterface myInterface = () -> System.out.println("Hello, Lambda!");myInterface.myMethod();}
}

在上面的示例中,我們定義了一個函數式接口MyInterface,它只有一個抽象方法myMethod。然后,我們使用Lambda表達式來實現這個接口,并在myMethod方法中打印一條消息。最后,我們創建了一個接口實例并調用myMethod方法。

  1. 上下文推斷:Lambda表達式的參數類型可以通過上下文推斷得出,無需顯式指定。這是Java 8引入的類型推斷機制的一部分。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));

在這個例子中,Lambda表達式name -> System.out.println(name)被傳遞給forEach方法。編譯器會根據forEach方法的參數類型推斷出Lambda表達式的參數類型為String。

  1. 方法引用:Lambda表達式可以使用方法引用來簡化代碼,雙冒號(:😃。方法引用是指直接引用已有方法的方式,可以通過類名、對象實例或超類來引用方法。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");names.stream().map(String::toUpperCase).forEach(System.out::println);

在這個例子中,String::toUpperCase是一個方法引用,它引用了String類的toUpperCase方法。在map方法中,每個元素都會被轉換為大寫。然后,使用forEach方法將轉換后的結果打印出來。方法引用使代碼更加簡潔,不需要編寫Lambda表達式來調用toUpperCase方法。

1.3、方法引用,雙冒號(::)

在Lambda表達式中,雙冒號(::)是一種特殊的語法,用于引用方法或構造函數。它可以用于以下幾種情況:

  1. 方法引用:使用雙冒號(::)來引用一個已經存在的方法。例如,假設有一個函數式接口Function,它有一個抽象方法apply,可以使用方法引用來引用一個已經存在的方法作為apply的實現。例如:
Function<String, Integer> function = Integer::parseInt;

這里,Integer::parseInt表示引用了Integer類的靜態方法parseInt作為apply方法的實現。

  1. 構造函數引用:使用雙冒號(::)來引用一個構造函數。例如,假設有一個函數式接口Supplier,它有一個抽象方法get,可以使用構造函數引用來引用一個構造函數作為get方法的實現。例如:
Supplier<List<String>> supplier = ArrayList::new;

這里,ArrayList::new表示引用了ArrayList類的構造函數作為get方法的實現。

  1. 數組引用:使用雙冒號(::)來引用一個數組。例如,可以使用int[]::new來引用一個整型數組的構造函數。

2、Lambda 表達式最佳實踐

2.1、簡單使用示例

以下是一些使用 Lambda 表達式的示例:

// 作為方法的參數
List<String> names = Arrays.asList("Alice", "Bob", "Carol");
names.sort((a, b) -> b.compareTo(a));// 作為構造函數的參數
Button button = new Button(() -> System.out.println("Click"));// 作為成員變量的初始值
Map<String, String> map = new HashMap<>();
map.put("key", "value");// 作為局部變量的初始值
int sum = names.stream().mapToInt(String::length).sum();

Lambda 表達式可以提高代碼的可讀性和可維護性,因此在編寫 Java 代碼時,我們應該盡可能使用 Lambda 表達式。

2.2、Lambda表達式最佳實踐

以下是使用Lambda表達式的一些最佳實踐:

  1. 使用合適的函數式接口:Lambda表達式需要與函數式接口一起使用。函數式接口是只包含一個抽象方法的接口。在選擇函數式接口時,確保它與Lambda表達式的參數和返回類型匹配。

  2. 保持Lambda表達式簡潔:Lambda表達式的主要目的是使代碼更加簡潔和易讀。因此,應盡量避免編寫過于復雜的Lambda表達式。如果Lambda表達式變得過于冗長或復雜,可以考慮將其提取為一個獨立的方法或使用方法引用。

  3. 使用方法引用:方法引用是Lambda表達式的一種簡化形式,可以使代碼更加簡潔和易讀。如果Lambda表達式只是簡單地調用一個已經存在的方法,可以考慮使用方法引用來代替Lambda表達式。

  4. 避免副作用:Lambda表達式應該是無副作用的,即不會對外部狀態產生影響。這有助于提高代碼的可讀性和可維護性。如果Lambda表達式需要修改外部狀態,應該使用其他方式來處理,例如使用局部變量或實例變量。

  5. 使用類型推斷:在Lambda表達式中,編譯器可以根據上下文推斷參數類型。因此,可以省略參數類型的顯式聲明,使代碼更加簡潔。但是,如果Lambda表達式的參數類型不明確或不容易理解,最好顯式聲明參數類型,以提高代碼的可讀性。

  6. 使用Lambda表達式的流式操作:Lambda表達式與流式操作(Stream API)結合使用可以實現更加簡潔和功能強大的代碼。流式操作提供了一種流暢的方式來處理集合數據,可以使用Lambda表達式來定義各種操作,如過濾、映射、排序等。

總的來說,使用Lambda表達式應該注重代碼的簡潔性、可讀性和可維護性。合理選擇函數式接口、使用方法引用、避免副作用以及充分利用類型推斷和流式操作等技巧,可以使Lambda表達式的使用更加高效和優雅。

二、Steam API

Java 8 引入了新的 Stream API,它提供了一種更簡單、更高效的方式來處理集合。Stream API 是一個函數式編程 API,它允許我們對集合中的元素進行各種操作,而無需使用傳統的 for 循環。

Stream API 的核心是 Stream 對象,它表示一個元素序列。Stream 可以由集合創建,也可以由其他 Stream 創建。Stream 可以通過各種方式進行操作,包括過濾、映射、聚合和收集。

1、Stream API 常見使用

Stream API 的使用非常簡單。要創建一個 Stream,我們可以使用集合的 stream() 方法。例如,以下代碼創建了一個包含數字 1 到 10 的 Stream:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> stream = numbers.stream();

Stream 可以通過各種方式進行操作。最常見的操作是過濾和映射。過濾操作用于從 Stream 中選擇滿足某些條件的元素。例如,以下代碼使用 filter() 方法從 Stream 中選擇所有偶數:

Stream<Integer> evenNumbers = stream.filter(n -> n % 2 == 0);

映射操作用于將 Stream 中的元素轉換為另一種類型的元素。例如,以下代碼使用 map() 方法將 Stream 中的數字轉換為字符串:

Stream<String> strings = stream.map(n -> String.valueOf(n));

Stream 還可以通過聚合操作來計算結果。聚合操作用于將 Stream 中的元素匯總到一個單一的值。例如,以下代碼使用 sum() 方法計算 Stream 中所有元素的總和:

int sum = stream.sum();

Stream 還可以通過收集操作將結果保存到集合中。例如,以下代碼使用 collect() 方法將 Stream 中的元素收集到一個列表中:

List<Integer> list = stream.collect(Collectors.toList());

Stream API 提供了一種非常簡單、高效的方式來處理集合。它可以幫助我們編寫更簡潔、更可讀的代碼。

2、Stream API 使用示例

以下是一些使用 Stream API 的示例:

  • 計算集合中所有元素的總和:
int sum = numbers.stream().mapToInt(n -> n).sum();
  • 計算集合中所有元素的平均值:
double average = numbers.stream().mapToInt(n -> n).average().getAsDouble();
  • 查找集合中最大的元素:
Optional<Integer> max = numbers.stream().max(Comparator.comparing(n -> n));
  • 查找集合中所有的偶數:
Stream<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0);
  • 將集合中的元素轉換為字符串:
Stream<String> strings = numbers.stream().map(n -> String.valueOf(n));
  • 將集合中的元素收集到一個列表中:
List<Integer> list = numbers.stream().collect(Collectors.toList());
  • 將集合中的元素保存到文件中:
numbers.stream().forEach(n -> System.out.println(n));

3、Stream API 核心方法

下面常用的Stream API方法:

方法描述類型使用示例
filter(Predicate<T> predicate)過濾流中的元素,只保留滿足條件的元素中間操作stream.filter(x -> x > 5)
map(Function<T, R> mapper)對流中的每個元素應用一個函數,并將結果映射為一個新的流中間操作stream.map(x -> x * 2)
flatMap(Function<T, Stream<R>> mapper)對流中的每個元素應用一個函數,并將結果扁平化為一個新的流中間操作stream.flatMap(x -> Stream.of(x, x + 1))
distinct()去除流中的重復元素中間操作stream.distinct()
sorted()對流中的元素進行排序中間操作stream.sorted()
limit(long maxSize)限制流中元素的數量不超過指定的最大值中間操作stream.limit(10)
skip(long n)跳過流中的前n個元素中間操作stream.skip(5)
forEach(Consumer<T> action)對流中的每個元素執行指定的操作終止操作stream.forEach(System.out::println)
collect(Collector<T, A, R> collector)將流中的元素收集到一個可變容器中,如List、Set或Map終止操作stream.collect(Collectors.toList())
reduce(BinaryOperator<T> accumulator)將流中的元素按照指定的操作進行歸約,得到一個結果終止操作stream.reduce(0, (a, b) -> a + b)
anyMatch(Predicate<T> predicate)檢查流中是否存在滿足條件的元素終止操作stream.anyMatch(x -> x > 5)
allMatch(Predicate<T> predicate)檢查流中的所有元素是否都滿足條件終止操作stream.allMatch(x -> x > 0)
noneMatch(Predicate<T> predicate)檢查流中是否沒有任何元素滿足條件終止操作stream.noneMatch(x -> x < 0)
findFirst()返回流中的第一個元素終止操作stream.findFirst()
findAny()返回流中的任意一個元素終止操作stream.findAny()
count()返回流中的元素數量終止操作stream.count()
min(Comparator<T> comparator)返回流中的最小元素終止操作stream.min(Comparator.naturalOrder())
max(Comparator<T> comparator)返回流中的最大元素終止操作stream.max(Comparator.naturalOrder())

這些方法根據其功能和使用方式可以分為兩種類型:中間操作和終止操作。中間操作返回一個新的流,可以被鏈式調用,而終止操作會產生一個最終結果或副作用。根據具體的需求,可以根據需要組合使用這些方法來處理和操作流中的元素。

4、Stream 可以配合哪些類使用

Stream 可以配合多種類使用,包括但不限于以下類:

  1. Collection 接口:Stream 可以通過 Collection 接口的 stream() 方法來創建。
List<String> names = Arrays.asList("Alice", "Bob", "Carol");
Stream<String> stream = names.stream();
  1. Arrays 類:Stream 可以通過 Arrays 類的 stream() 方法來創建。
int[] numbers = {1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(numbers);
  1. BufferedReader 類:Stream 可以通過 BufferedReader 類的 lines() 方法來創建。
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
Stream<String> lines = reader.lines();
  1. IntStream、LongStream、DoubleStream 類:這些類提供了特定類型的 Stream,可以用于處理基本類型的元素。
IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
LongStream longStream = LongStream.range(1, 10);
DoubleStream doubleStream = DoubleStream.generate(Math::random);
  1. Files 類:Stream 可以通過 Files 類的 lines() 方法來讀取文件內容并創建。
Stream<String> lines = Files.lines(Paths.get("file.txt"));
  1. Pattern 類:Stream 可以通過 Pattern 類的 splitAsStream() 方法來將字符串拆分為 Stream。
Pattern pattern = Pattern.compile("\\s+");
Stream<String> words = pattern.splitAsStream("Hello World");
  1. Random 類:Stream 可以通過 Random 類的 ints()longs()doubles() 方法來生成隨機數的 Stream。
Random random = new Random();
IntStream randomInts = random.ints(5, 1, 10);
  1. StreamSupport 類:Stream 可以通過 StreamSupport 類的 stream() 方法來創建自定義的 Stream。
Iterable<String> iterable = Arrays.asList("Alice", "Bob", "Carol");
Stream<String> stream = StreamSupport.stream(iterable.spliterator(), false);

這些類提供了不同的方式來創建和處理 Stream,可以根據具體的需求選擇合適的類。配合不同的類使用 Stream 可以實現豐富的功能和靈活的操作。

參考

  • 官方文檔

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539510.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539510.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539510.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用T-SQL語句操作數據表-刪除數據

1.使用 delete 語句刪除表中的數據&#xff1a;語法&#xff1a;delete from <表名> [where <刪除條件>]delete 是刪除的意思 where是選填內容可以不加&#xff0c;但是不加條件的話是刪除整個表 例子&#xff1a;delete from 成績表 where 姓名張三含義&#xff1…

Oracle expdp/impdp導出導入命令及數據庫備份

經常報錯&#xff1a; ORA-39002: invalid operation ORA-39070: Unable to open the log file. ORA-29283: invalid file operation ORA-06512: at "SYS.UTL_FILE", line 536 ORA-29283: invalid file operation 解決方法&#xff1a; 1、 CREATE OR REPLACE DI…

exfat單元分配要設置多少_微軟宣布,支持往Linux內核里添加exFAT存儲了!跨系統存儲的福音...

栗子 發自 凹非寺 量子位 報道 | 公眾號 QbitAIexFAT&#xff0c;是微軟開發的文件系統&#xff0c;為閃存而生。你的U盤、SD卡、手機等等存儲設備&#xff0c;能存4G以上的大文件&#xff0c;很大程度上是它的功勞。可exFAT一直是專有的&#xff0c;微軟手握多項專利。所以&am…

在linux中安裝oracle中文包,在Linux命令行下安裝Oracle 10g

Oracle 10g支持在命令行下用靜默模式(Silent)安裝&#xff0c;給那些沒有安裝圖形界面的Linux系統提供了極大的便利。下面以Fedora Core 6為例&#xff0c;介紹在命令行下安裝OracleOracle 10g的方法。1 安裝前的準備準備工作要用登錄為root用戶來進行。1.1 選擇安裝環境的語言…

Jetbrains 系 IDE 編輯器的代碼提示功能

著名的 Jetbrains 可謂編程界的一大福音&#xff0c;眾多有名代碼編輯器比如 ItelliJ IDEA、PHPStorm、WebStorm、PyCharm 等&#xff0c;均出自這家公司麾下。 對于中國的Java開發者來說&#xff0c;可能使用 Eclipse 的人最多。 使用Idea的程序員也不少, 而且每個人都在鼓吹其…

Oracle下的Databse,Instance,Schemas

1、DATABASE&#xff0c;對oracle而言&#xff0c;是指物理上的數據庫&#xff0c;一般你安裝了一個oracle的數據庫軟件后&#xff0c;就是一個database。 2、instance&#xff0c;在同一個數據庫上&#xff0c;可以建立多個實例&#xff0c;這些實例互相不干擾&#xff0c;每個…

oracle實驗數據庫和表,1oracle創建數據庫和表.doc

1oracle創建數據庫和表.doc實驗一&#xff1a;創建數據庫和表一、實驗目的1. 掌握使用DBCA創建數據庫2. 掌握手工創建Oracle數據庫的方法3. 掌握創建數據表的方法二、實驗內容及步驟1. 使用DBCA創建數據庫(1) 打開DBCA組件,創建數據庫sale.(2) 安裝完后進入D:\oracle\product\1…

tkmybatis 子查詢_真假童子命符箓道長教你如何查詢

童子命查詢方法一&#xff1a;童子命在相術里&#xff0c;指的是一生都霉運連連如過本命年的人。古代關于真童子命查詢有口訣“春秋甲寅子&#xff0c;冬夏卯未辰&#xff1b; 金木乙卯未&#xff0c;水火庚辛壬&#xff1b; 土命逢辰巳&#xff0c;童子定為真”解釋上面的口訣…

使用 nvm 安裝 nodejs 和 npm

使用 nvm 可以方便的進行 nodejs 的安裝和版本管理。其實最開始使用的是 n 命令&#xff0c;命令簡潔到極致了&#xff0c;無奈總是安裝不成功&#xff0c;往往下載一部分就報 curl 錯誤。然后又找到這個 nvm&#xff0c;配合淘寶源&#xff0c;簡單快捷&#xff5e; 1.到 nvm …

ECLIPSE配置OSGI服務器

eclipse版本如下&#xff1a; Eclipse Java EE IDE for Web Developers. Version: Mars Release (4.5.0) Build id: 20150621-1200 ------------------------ 1、進入eclipse-----run----run configuration---osgi framework---new 2、取消全選 3、在搜索框中輸入 osgi&a…

oracle ebs r12財務月結基礎講座20090823,095921_OracleEBSR12財務月結基礎講座20090823課件.ppt...

095921_OracleEBSR12財務月結基礎講座20090823課件2009年8月23日方亞兵、鞏學偉;1、月結概述 1.1)月結與對帳 1.2)子模塊與總帳之間的關系 1.3)關帳順序2、各模塊詳細結帳流程及對帳 2.1)應付 2.2)采購 2.3)庫存 2.4)應收 2.5)資產 2.6)PAC 2.7)總帳3、應收模塊業務規則介紹4、…

AD19 add pins to nets錯誤_為什么我認為Rust的Result錯誤處理方式不如Exception

由于是對技術的個人評判&#xff0c;歡迎理性討論。我曾經也當過純函數式的腦殘粉&#xff0c;認為宇宙第一棒的代數數據結構用來處理錯誤&#xff0c;是無上的優雅和絕對的安全。一個看似人畜無害的接口拋出異常帶來的崩潰&#xff0c;是各類疑難雜癥的罪魁禍首。綜合起來&…

Java @Transient 注解使用

2019獨角獸企業重金招聘Python工程師標準>>> 我們建實體類的時候啊&#xff0c;有時候實體類的屬性和數據庫表字段不一致的時候&#xff0c;比如多一個屬性&#xff0c;那你不加這個注解就會報錯&#xff0c;因為映射的時候會提示&#xff08;提示啥我給忘了&#x…

Myeclipse/eclipse 安裝查看class文件的插件

從http://www.oschina.net/project/tag/317/decompiler?lang19&os0&sortview 中下載了 也可到我的網盤&#xff1a;http://pan.baidu.com/s/1eS5BMcM 下載 Java反編譯工具jad &#xff08;jad.exe&#xff09;和 Java反編譯插件 Jadclipse &#xff08;net.sf.jadcl…

oracle—ebs_采購功能點操作手冊,oracle—EBS_采購功能點操作手冊

erp實施企業采購模塊構架及日常業務操作指導“人力資源”頁簽可以設置是否“使用審批層次結構”來決定采購單據的審批路徑。如不選定&#xff0c;則表示采購單據將使用員工的“主管”結構來進行審批。“員工編號”方法默認自業務組定義時的“員工編號生成”方法設置。1.2采購選…

Https的前世今生

1、年前會議 馬上要過年了&#xff0c;公司業務上的需求也少了很多&#xff0c;這不&#xff0c;王小二他們召開了一場技術會議&#xff0c;盤點年前能干點啥。 只見C哥寫了一份清單&#xff0c;其中一項是全站升級https。 C哥說&#xff1a;https是一種趨勢&#xff0c;但目前…

combobox控件 如何把三角形放大_初中數學|全等三角形全部知識點總結

今天&#xff0c;琦老師為大家整理了[初中數學重要考點&#xff0c;全等三角形的全部知識點]&#xff0c;希望幫助大家中考數學快速提分( #小學數學#初中數學#數學)除了圖片內容&#xff0c;大米君也為大家分享[如何靈活運用這些知識點的方法]大家記得跟著做起來哦~提高復習效果…

Spring中引入其他配置文件

原文&#xff1a;http://www.cnblogs.com/LiuChunfu/p/5605473.html ------------------------------------------------------------------------------ 一、引入其他 模塊XML   在Spring的配置文件&#xff0c;有時候為了分模塊的更加清晰的進行相關實體類的配置。 比如…

oracle不要重復記錄,Oracle中去重復記錄 不用distinct

用distinct關鍵字只能過濾查詢字段中所有記錄相同的(記錄集相同)&#xff0c;而如果要指定一個字段卻沒有效果&#xff0c;另外distinct關鍵字會排序&#xff0c;效率很低 。select distinct name from t1 能消除重復記錄&#xff0c;但只能取一個字段&#xff0c;現在要同時取…

miui游戲驅動程序偏好設置_米粉必看:小米官方教你如何關閉 MIUI 廣告 - 小米,MIUI...

IT之家 11 月 9 日消息 小米的 MIUI 在用戶心中的口碑一直是比較好的&#xff0c;但該系統也并非完美&#xff0c;被吐槽的較多的一個點就是系統內的廣告比較多。今天&#xff0c;小米官方微博 小米服務那些事 分享了幾個能夠減少 MIUI 廣告的方法&#xff0c;米粉不妨了解一下…