Stream流(3)
3.1 概述
Java8的Stream使用的是函數式編程模式,如同它的名字一樣,它可以被用來對集合或數組進行鏈狀流式的操作。可以更方便的讓我們對集合或數組操作。鏈式調用操作
3.2 案例數據準備
<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency></dependencies> @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode//用于后期的去重使用 public class Author {//idprivate Long id;//姓名private String name;//年齡private Integer age;//簡介private String intro;//作品private List<Book> books; } @Data @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode//用于后期的去重使用 public class Book {//idprivate Long id;//書名private String name;//分類private String category;//評分private Integer score;//簡介private String intro;} 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.3 快速入門
3.3.1 需求
我們可以調用getAuthors方法獲取到作家的集合。現在需要打印所有年齡小于18的作家的名字,并且要注意去重。3.3.2 實現
//打印所有年齡小于18的作家的名字,并且要注意去重List<Author> authors = getAuthors();authors.stream()//把集合轉換成流.distinct()//先去除重復的作家.filter(author -> author.getAge()<18)//篩選年齡小于18的.forEach(author -> System.out.println(author.getName()));//遍歷打印名字3.4 常用操作
3.4.1 創建流stream
單列集合: 集合對象.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);雙列集合:轉換成單列集合后再創建
Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); 單列Set
3.4.2 中間操作
filter
可以對流中的元素進行條件過濾,符合過濾條件的才能繼續留在流中。
-==
例如:
打印所有姓名長度大于1的作家的姓名 List<Author> authors = getAuthors();authors.stream().filter(author -> author.getName().length()>1).forEach(author -> System.out.println(author.getName()));map
不會Lambda表達式、函數式編程?你確定能看懂公司代碼?-java8函數式編程(Lambda表達式,Optional,Stream流)從入門到精通-最通俗易懂_嗶哩嗶哩_bilibili
可以把對流中的元素進行計算或轉換。比如可以把對象中的某個屬性取出,或者對對象的數據進行操作
Function 匿名類的 new Function <A,B> 其中A是固定的,是流中的類,B是要返回的類型,也就是修改后流中元素類型
例如:
不會Lambda表達式、函數式編程?你確定能看懂公司代碼?-java8函數式編程(Lambda表達式,Optional,Stream流)從入門到精通-最通俗易懂_嗶哩嗶哩_bilibili
//可以在forEach里面嵌套authors.stream().map(author -> author.getBooks()).forEach(books -> books.stream().filter(book -> book.getScore() > 88).forEach(book -> System.out.println(book)));authors.stream().map(author -> author.getBooks()).forEach(books -> System.out.println(books));flatMap把流里面的集合給整合到一個流里面
distinct
可以去除流中的重復元素。例如:
打印所有作家的姓名,并且要求其中不能有重復元素。 List<Author> authors = getAuthors();authors.stream().distinct().forEach(author -> System.out.println(author.getName()));注意:distinct方法是依賴Object的equals方法來判斷是否是相同對象的。所以需要注意重寫equals方法。
sorted
可以對流中的元素進行排序。例如:
對流中的元素按照年齡進行降序排序,并且要求不能有重復的元素。 List<Author> authors = getAuthors(); // 對流中的元素按照年齡進行降序排序,并且要求不能有重復的元素。authors.stream().distinct().sorted().forEach(author -> System.out.println(author.getAge())); List<Author> authors = getAuthors(); // 對流中的元素按照年齡進行降序排序,并且要求不能有重復的元素。authors.stream().distinct().sorted((o1, o2) -> o2.getAge()-o1.getAge()).forEach(author -> System.out.println(author.getAge()));注意:如果調用空參的sorted()方法,需要流中的元素是實現了Comparable。
limit
可以設置流的最大長度,超出的部分將被拋棄。例如:
對流中的元素按照年齡進行降序排序,并且要求不能有重復的元素,然后打印其中年齡最大的兩個作家的姓名。 List<Author> authors = getAuthors();authors.stream().distinct().sorted().limit(2).forEach(author -> System.out.println(author.getName()));peek
補充的
挑出操作,如果想對數據進行某些操作,如:讀取、編輯修改等。 可以理解為提前消費``
內部是消費者接口
public class Main {public static void main(String[] args) {User w = new User("w",10);User x = new User("x",11);User y = new User("y",12);Stream.of(w,x,y).peek(e->{e.setName(e.getAge()+e.getName());}) //重新設置名字 變成 年齡+名字.forEach(e->System.out.println(e.toString()));}static class User {private String name;private int age;public User(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;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}}}skip
跳過流中的前n個元素,返回剩下的元素例如:
打印除了年齡最大的作家外的其他作家,要求不能有重復元素,并且按照年齡降序排序。 // 打印除了年齡最大的作家外的其他作家,要求不能有重復元素,并且按照年齡降序排序。List<Author> authors = getAuthors();authors.stream().distinct().sorted().skip(1).forEach(author -> System.out.println(author.getName()));flatMap
map只能把一個對象轉換成另一個對象來作為流中的元素。而flatMap可以把一個對象轉換成多個對象作為流中的元素。把流里面的集合也變為拆包為流的一部分
例一:
打印所有書籍的名字。要求對重復的元素進行去重。 // 打印所有書籍的名字。要求對重復的元素進行去重。List<Author> authors = getAuthors();authors.stream().flatMap(author -> author.getBooks().stream()).distinct().forEach(book -> System.out.println(book.getName()));例二:
打印現有數據的所有分類。要求對分類進行去重。不能出現這種格式:哲學,愛情 // 打印現有數據的所有分類。要求對分類進行去重。不能出現這種格式:哲學,愛情 愛情List<Author> authors = getAuthors();authors.stream().flatMap(author -> author.getBooks().stream()).distinct().flatMap(book -> Arrays.stream(book.getCategory().split(","))).distinct().forEach(category-> System.out.println(category));3.4.3 終結操作
forEach
對流中的元素進行遍歷操作,我們通過傳入的參數去指定對遍歷到的元素進行什么具體操作。例子:
輸出所有作家的名字作家的book 是一個List<Book>
// 輸出所有作家的名字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
封裝的reduce
可以用來或者流中的最值。
使用起來和sorted類似 均為利用Comparator接口
例子:
分別獲取這些作家的所出書籍的最高分和最低分并打印 // 分別獲取這些作家的所出書籍的最高分和最低分并打印。//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集合。List<Author> authors = getAuthors();List<String> nameList = authors.stream().map(author -> author.getName()).collect(Collectors.toList());System.out.println(nameList); 獲取一個所有書名的Set集合。 // 獲取一個所有書名的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>要先去重,如果不去重的話,一旦有重復的key 他會報錯,他不會自己去除重復
// 獲取一個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);匹配
返回值均為boolean 類型
anyMatch
可以用來判斷是否有任意符合匹配條件的元素,結果為boolean類型。例子:
判斷是否有年齡在29以上的作家 // 判斷是否有年齡在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歲的。 // 判斷作家是否都沒有超過100歲的。List<Author> authors = getAuthors();boolean b = authors.stream().noneMatch(author -> author.getAge() > 100);System.out.println(b);查找
返回Option<T>
findAny
獲取流中的任意一個元素。該方法沒有辦法保證獲取的一定是流中的第一個元素。例子:
獲取任意一個年齡大于18的作家,如果存在就輸出他的名字 // 獲取任意一個年齡大于18的作家,如果存在就輸出他的名字List<Author> authors = getAuthors();Optional<Author> optionalAuthor = authors.stream().filter(author -> author.getAge()>18).findAny();optionalAuthor.ifPresent(author -> System.out.println(author.getName()));不會Lambda表達式、函數式編程?你確定能看懂公司代碼?-java8函數式編程(Lambda表達式,Optional,Stream流)從入門到精通-最通俗易懂_嗶哩嗶哩_bilibili
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歸并
ifPresent如果存在
不會Lambda表達式、函數式編程?你確定能看懂公司代碼?-java8函數式編程(Lambda表達式,Optional,Stream流)從入門到精通-最通俗易懂_嗶哩嗶哩_bilibili
對流中的數據按照你指定的計算方式計算出一個結果。(縮減操作)reduce的作用是把stream中的元素給組合起來,我們可以傳入一個初始值,它會按照我們的計算方式依次拿流中的元素和初始化值進行計算,計算結果再和后面的元素計算。reduce兩個參數的重載形式內部的計算方式如下: T result = identity; for (T element : this stream)result = accumulator.apply(result, element) return result; 其中identity就是我們可以通過方法參數傳入的初始值,accumulator的apply具體進行什么計算也是我們通過方法參數來確定的。例子:
使用reduce求所有作者年齡的和先Map轉換 因為操作的類型是流中的類型
// 使用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求所有作者中年齡的最大值 // 使用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求所有作者中年齡的最小值 // 使用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一個參數的重載形式內部的計算把第一個元素變為初始化值
boolean foundAny = false;T result = null;for (T element : this stream) {if (!foundAny) {foundAny = true;result = element;}elseresult = accumulator.apply(result, element);}return foundAny ? Optional.of(result) : Optional.empty(); 如果用一個參數的重載方法去求最小值代碼如下: // 使用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));3.5 注意事項
-
惰性求值(如果沒有終結操作,沒有中間操作是不會得到執行的)
-
流是一次性的(一旦一個流對象經過一個終結操作后。這個流就不能再被使用)
-
不會影響原數據(我們在流中可以多數據做很多處理。但是正常情況下是不會影響原來集合中的元素的。這往往也是我們期望的) 只要不調用原數據的set 方法
總結
以上是生活随笔為你收集整理的Stream流(3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PDF密码如何解除
- 下一篇: Mac OS使用技巧之三:发射无线网络信