日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java】函数式编程学习笔记——Stream流

發布時間:2023/12/9 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java】函数式编程学习笔记——Stream流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習視頻:https://www.bilibili.com/video/BV1Gh41187uR?p=1

(1)【Java】函數式編程學習筆記——Lambda表達式
(2)【Java】函數式編程學習筆記——Stream流
(3)【Java】函數式編程學習筆記——Optional
(4)【Java】函數式編程學習筆記——函數式接口、方法引用


文章目錄

  • 1 概述
  • 2 案例數據準備
  • 3 快速入門
  • 4 常用操作
    • 4.1 創建流
    • 4.2 中間操作
    • 4.3 終結操作
  • 5 注意事項
  • 6 常用

1 概述

Java8的Stream使用的是函數式編程模式,如同它的名字一樣, 它可以被用來對集合或數組進行鏈狀流式的操作。可以更方便的讓我們對集合或數組操作。

2 案例數據準備

@Data @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode public class Author {private Long id;private String name;private Integer age;private String intro;private List<Book> books; } @Data @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode public class Book {private Long id;private String name;private String category;private Integer score;private String info; } private static List<Author> getAuthors() {//數據初始化Author author = new Author(1L,"蒙多",33,"一個從菜刀中明悟哲理的祖安人",null);Author author2 = new Author(2L,"亞拉索",15,"狂風也追逐不上他的思考速度",null);Author author3 = new Author(3L,"易",14,"是這個世界在限制他的思維",null);Author author4 = new Author(3L,"易",14,"是這個世界在限制他的思維",null);//書籍列表List<Book> books1 = new ArrayList<>();List<Book> books2 = new ArrayList<>();List<Book> books3 = new ArrayList<>();books1.add(new Book(1L,"刀的兩側是光明與黑暗","哲學,愛情",88,"用一把刀劃分了愛恨"));books1.add(new Book(2L,"一個人不能死在同一把刀下","個人成長,愛情",99,"講述如何從失敗中明悟真理"));books2.add(new Book(3L,"那風吹不到的地方","哲學",85,"帶你用思維去領略世界的盡頭"));books2.add(new Book(3L,"那風吹不到的地方","哲學",85,"帶你用思維去領略世界的盡頭"));books2.add(new Book(4L,"吹或不吹","愛情,個人傳記",56,"一個哲學家的戀愛觀注定很難把他所在的時代理解"));books3.add(new Book(5L,"你的劍就是我的劍","愛情",56,"無法想象一個武者能對他的伴侶這么的寬容"));books3.add(new Book(6L,"風與劍","個人傳記",100,"兩個哲學家靈魂和肉體的碰撞會激起怎么樣的火花呢?"));books3.add(new Book(6L,"風與劍","個人傳記",100,"兩個哲學家靈魂和肉體的碰撞會激起怎么樣的火花呢?"));author.setBooks(books1);author2.setBooks(books2);author3.setBooks(books3);author4.setBooks(books3);List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));return authorList; }

3 快速入門

需求

我們可以調用getAuthors方法獲取到作家的集合。現在需要打印所有年齡小于18的作家的名字,并且要注意去重。

實現

authors.stream():把集合轉換成流,返回的就是Stream對象。
.distinct():去重,去除重復項
.filter():過濾,根據條件進行篩選
.forEach():對結果進行遍歷處理。

public static void main(String[] args) {List<Author> authors = getAuthors();authors.stream() // 把集合轉換為流.distinct() // 去重.filter(author -> author.getAge() < 18) // 年齡小于18.forEach(author -> System.out.println(author.getName())); }

打斷點,進行調試:

4 常用操作

4.1 創建流

單列集合: 集合對象.stream()

List<Author> authors = getAuthors(); Stream<Author> stream = authors.stream();

數組:Arrays.stream(數組)或者使用Stream.of來創建

Integer[] arr = {1,2,3,4,5}; Stream<Integer> stream = Arrays.stream(arr); Stream<Integer> stream2 = Stream.of(arr);

雙列集合:轉換成單列集合后再創建

Map<String,Integer> map = new HashMap<>(); map.put("蠟筆小新",19); map.put("黑子",17); map.put("日向翔陽",16);Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();

4.2 中間操作

方法用法
filter可以對流中的元素進行條件過濾,符合過濾條件的才能繼續留在流中。
map可以把對流中的元素進行計算或轉換。
distinct可以去除流中的重復元素。
sorted可以對流中的元素進行排序。
limit可以設置流的最大長度,超出的部分將被拋棄。
skip跳過流中的前n個元素,返回剩下的元素。
flatMap可以把一個對象轉換成多個對象作為流中的元素。

filter:可以對流中的元素進行條件過濾,符合過濾條件的才能繼續留在流中。

.filter(author -> author.getName().length()>1)

map:可以把對流中的元素進行計算或轉換。

.map(author -> author.getName()).map(age->age+10)

distinct:可以去除流中的重復元素

注意:distinct方法是依賴Object的equals方法來判斷是否是相同對象的。所以需要注意重寫equals方法。

sorted:可以對流中的元素進行排序

.sorted((o1, o2) -> o2.getAge()-o1.getAge())

注意:如果調用空參的sorted()方法,需要流中的元素是實現了Comparable。

limit:可以設置流的最大長度,超出的部分將被拋棄。

.limit(2) 最大長度為2

skip:跳過流中的前n個元素,返回剩下的元素

.skip(1) //跳過第一個元素

flatMap:map只能把一個對象轉換成另一個對象來作為流中的元素。而flatMap可以把一個對象轉換成多個對象作為流中的元素。

舉例1

打印所有書籍的名字,要求對重復的元素進行去重。

public static void main(String[] args) {List<Author> authors = getAuthors();// 打印所有書籍的名字。要求對重復的元素進行去重。authors.stream().flatMap(author -> author.getBooks().stream()).distinct().forEach(book -> System.out.println(book.getName())); }

每一個author里包含一個book集合,通過flatMap將多個book集合映射到同一個流當中。

舉例2

打印現有數據的所有分類。要求對分類進行去重。不能出現這種格式:“哲學,愛情”

public static void main(String[] args) {List<Author> authors = getAuthors();// 打印所有書籍的名字。要求對重復的元素進行去重。authors.stream().flatMap(author -> author.getBooks().stream()).distinct().flatMap(book -> Arrays.stream(book.getCategory().split(","))).distinct().forEach(System.out::println); }

4.3 終結操作

方法用法
forEach對流中的元素進行遍歷操作,我們通過傳入的參數去指定對遍歷到的元素進行什么具體操作。
count可以用來獲取當前流中元素的個數。
max&min可以用來或者流中的最值。
collect把當前流轉換成一個集合。
anyMatch可以用來判斷是否有任意符合匹配條件的元素,結果為boolean類型。
allMatch可以用來判斷是否都符合匹配條件,結果為boolean類型。如果都符合結果為true,否則結果為false。
noneMatch可以判斷流中的元素是否都不符合匹配條件。如果都不符合結果為true,否則結果為false。
findAny獲取流中的任意一個元素。該方法沒有辦法保證獲取的一定是流中的第一個元素。
findFirst獲取流中的第一個元素。
reduce歸并

forEach:對流中的元素進行遍歷操作,我們通過傳入的參數去指定對遍歷到的元素進行什么具體操作。

// 輸出所有作家的名字 List<Author> authors = getAuthors();authors.stream().map(author -> author.getName()).distinct().forEach(name-> System.out.println(name));

count:可以用來獲取當前流中元素的個數。

// 打印這些作家的所出書籍的數目,注意刪除重復元素。 List<Author> authors = getAuthors();long count = authors.stream().flatMap(author -> author.getBooks().stream()).distinct().count(); System.out.println(count);

max&min:可以用來或者流中的最值。

// 分別獲取這些作家的所出書籍的最高分和最低分并打印。 // Stream<Author> -> Stream<Book> ->Stream<Integer> -> 求值List<Author> authors = getAuthors(); Optional<Integer> max = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).max((score1, score2) -> score1 - score2);Optional<Integer> min = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).min((score1, score2) -> score1 - score2);System.out.println(max.get()); System.out.println(min.get());

collect:把當前流轉換成一個集合。

// 獲取一個存放所有作者名字的List集合。 List<Author> authors = getAuthors(); List<String> nameList = authors.stream().map(author -> author.getName()).collect(Collectors.toList()); System.out.println(nameList); // 獲取一個所有書名的Set集合。 List<Author> authors = getAuthors(); Set<Book> books = authors.stream().flatMap(author -> author.getBooks().stream()).collect(Collectors.toSet());System.out.println(books); // 獲取一個Map集合,map的key為作者名,value為List<Book> List<Author> authors = getAuthors(); Map<String, List<Book>> map = authors.stream().distinct().collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));System.out.println(map);

anyMatch:可以用來判斷是否有任意符合匹配條件的元素,結果為boolean類型。

// 判斷是否有年齡在29以上的作家 List<Author> authors = getAuthors(); boolean flag = authors.stream().anyMatch(author -> author.getAge() > 29); System.out.println(flag);

allMatch:可以用來判斷是否都符合匹配條件,結果為boolean類型。如果都符合結果為true,否則結果為false。

// 判斷是否所有的作家都是成年人 List<Author> authors = getAuthors(); boolean flag = authors.stream().allMatch(author -> author.getAge() >= 18); System.out.println(flag);

noneMatch:可以判斷流中的元素是否都不符合匹配條件。如果都不符合結果為true,否則結果為false。

// 判斷作家是否都沒有超過100歲的。 List<Author> authors = getAuthors();boolean b = authors.stream().noneMatch(author -> author.getAge() > 100);System.out.println(b);

findAny:獲取流中的任意一個元素。該方法沒有辦法保證獲取的一定是流中的第一個元素。

// 獲取任意一個年齡大于18的作家,如果存在就輸出他的名字 List<Author> authors = getAuthors(); Optional<Author> optionalAuthor = authors.stream().filter(author -> author.getAge()>18).findAny();optionalAuthor.ifPresent(author -> System.out.println(author.getName()));

findFirst:獲取流中的第一個元素。

// 獲取一個年齡最小的作家,并輸出他的姓名。 List<Author> authors = getAuthors(); Optional<Author> first = authors.stream().sorted((o1, o2) -> o1.getAge() - o2.getAge()).findFirst();first.ifPresent(author -> System.out.println(author.getName()));

reduce:歸并

對流中的數據按照你指定的計算方式計算出一個結果。(縮減操作)

reduce的作用是把stream中的元素給組合起來,我們可以傳入一個初始值,它會按照我們的計算方式依次拿流中的元素和初始化值進行計算,計算結果再和后面的元素計算。

reduce兩個參數的重載形式內部的計算方式如下:

T result = identity; for (T element : this stream)result = accumulator.apply(result, element) return result;

其中identity就是我們可以通過方法參數傳入的初始值,accumulator的apply具體進行什么計算也是我們通過方法參數來確定的。

舉例

// 使用reduce求所有作者年齡的和 List<Author> authors = getAuthors(); Integer sum = authors.stream().distinct().map(author -> author.getAge()).reduce(0, (result, element) -> result + element); System.out.println(sum); // 使用reduce求所有作者中年齡的最大值 List<Author> authors = getAuthors(); Integer max = authors.stream().map(author -> author.getAge()).reduce(Integer.MIN_VALUE, (result, element) -> result < element ? element : result);System.out.println(max); // 使用reduce求所有作者中年齡的最小值 List<Author> authors = getAuthors(); Integer min = authors.stream().map(author -> author.getAge()).reduce(Integer.MAX_VALUE, (result, element) -> result > element ? element : result); System.out.println(min);

reduce由三種參數形式:

Optional<T> reduce(BinaryOperator<T> accumulator); T reduce(T identity, BinaryOperator<T> accumulator); <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

我們公共使用的是帶有兩個參數的形式,下面看一下一個參數的重載形式內部的計算

boolean foundAny = false; T result = null; // 初始是null,兩個參數的時候,初始值是我們定義的 for (T element : this stream) {if (!foundAny) { // 流當中的第一個元素設置為resultfoundAny = true;result = element;}elseresult = accumulator.apply(result, element); // 剩下的部分一樣。 } return foundAny ? Optional.of(result) : Optional.empty(); // 結果封裝為Optional返回

如果用一個參數的重載方法去求最小值代碼如下:

// 使用reduce求所有作者中年齡的最小值 List<Author> authors = getAuthors(); Optional<Integer> minOptional = authors.stream().map(author -> author.getAge()).reduce((result, element) -> result > element ? element : result); minOptional.ifPresent(age-> System.out.println(age));

5 注意事項

  • 惰性求值(如果沒有終結操作,沒有中間操作是不會得到執行的)
  • 流是一次性的(一旦一個流對象經過一個終結操作后。這個流就不能再被使用)
  • 不會影響原數據(我們在流中可以多數據做很多處理。但是正常情況下是不會影響原來集合中的元素的。這往往也是我們期望的)

6 常用

數組求和:total = Arrays.stream(arr).sum()

總結

以上是生活随笔為你收集整理的【Java】函数式编程学习笔记——Stream流的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。