Stream流的使用

Stream流的使用

本篇主要講解JDK8中 Stream流的使用, 包括如何 篩選 、切片、映射 、查找、匹配 、歸約 等等 每個類型都會有對應的案例 簡單易懂


 1.Stream的概念

 Stream API是JDK8新添加的處理集合的關鍵組件,這裡的Stream流和I/O流不同,Stream是對集合對象功能的增強,它專注對集合對象提供各種便利的操作,只要給出需要對其包含的元素執行什麼操作,比如“過濾掉長度大於10的字符串”、“獲取每個字符串的首字母”等,Stream會隱式地在內部進行遍歷,做出相應的數據轉換


 2.Stream流的創建


  2.1 從集合創建


<code>     List<integer> list = new ArrayList<>();/<integer>/<code>
<code>    //1.從集合創建流
list.stream();
list.parallelStream();/<code>

  2.2 從數組創建


<code>    //Arrays的靜態方法 stream  

Arrays.stream(new int[] {1, 2, 3,});/<code>

  2.3 創建數字流


<code>    //IntStream流 
int intarr[] = {1,2,3};
IntStream.of(1,2,3);
IntStream.of(intarr);/<code>
<code>    //LongStream流
long longarr[] = {1L , 2L , 3L};
LongStream.of(longarr);/<code>

  2.4 創建無限流


<code>     //通過Random的 ints longs doubles 創建一個無限流  一般要限制個數 通過 limit是限制個數/<code>
<code>    new Random().ints().limit(10).forEach((i) -> System.out.println(i));
new Random().longs();
new Random().doubles();/<code>

  2.5 自己創建Stream


<code>    通過 Stream.generate(Supplier s) 自己去實現Supplier 函數式接口,去提供數據/<code>
<code>    //如下 通過Random去提供
Random random = new Random();
Stream.generate(() -> random.nextInt()).limit(20).forEach((i) -> System.out.println(i));/<code>
<code>    //通過 Stream的 of        
Stream.of("Hello" , "Stream")
/<code>

 3.Stream提供的常用的方法

 Stream提供了一些便利的方法

<code>    map()  映射
filter() 過濾/篩選
limit() 限制數量
skip() 跳過數量
reduce() 歸約
distinct() 去重
sorted() 排序
collect() 收集 結合Collectors.toList()使用
forEach() 遍歷
...

/<code>

 4.Stream流的中間操作

Stream流的中間操作,就是這個操作返回還是一個Stream流,不是一個最終結果,中間操作比如要有一個終止操作的方法調用才會執行

Stream流的中間操作 分為2類 無狀態操作:當前的操作和其元素的前後沒有依賴關係
 有狀態操作:當前的操作的結果需要依賴其他的元素

Stream流的使用

 5.Stream流的終止操作

Stream流的終止操作,會返回一個最終的結果,只有有終止操作 中間操作才會執行

Stream流的終止操作 分為2類非短路操作:當前操作中間是不會斷的,也就是需要流中的數據全部執行完畢短路操作:當前操作不需要等待全部數據執行完畢,可能到某個數據執行完畢後就結束流

Stream流的使用


 6.篩選和切片


  • filter
  • distinct
  • limit
  • skip
<code>    

/<code>

 準備數據

<code>        //id name age 對應屬性
Student student = new Student(1, "johnny", 23);
Student student1 = new Student(2, "candy", 25);
Student student2 = new Student(2, "ruby", 25);
Student student3 = new Student(3, "lucy", 33);
Student student4 = new Student(4, "jack", 53);
/<code>
<code>        List<student> studentList = new ArrayList<>();
studentList.add(student);
studentList.add(student1);
studentList.add(student2);
studentList.add(student3);
studentList.add(student4);


/<student>/<code>

  6.1 謂詞篩選 filter

  Stream 接口支持 filter 方法,該操作會接受一個謂詞(一個返回 boolean的函數)作為參數,並返回一個包括所有符合謂詞的元素的流。

  如下:這個謂語就是 age>25

<code>      List<student> filterStudent = studentList.stream().filter(s -> s.getAge() > 25)
.collect(Collectors.toList());
/<student>/<code>

  6.2 篩選重複 distinct

Stream 接口支持 distinct 的方法, 它會返回一個元素各異(根據流所生成元素的 hashCode和equals方法實現)的流

<code>       //得到Student所有的年紀並且去重
List<integer> ageList = studentList.stream().map(s -> s.getAge())
.distinct()
.collect(Collectors.toList());
/<integer>/<code>

  6.3 限制元素 limit

Stream 支持limit(n)方法,該方法會返回一個不超過給定長度的流。所需的長度作為參數傳遞 給limit。如果流是有序的,則最多會返回前n個元素

<code>        List<integer> limitAgeList = studentList.stream().map(s -> s.getAge())
.limit(2)
.collect(Collectors.toList());
System.out.println(limitAgeList);/<integer>/<code>

6.4 跳過指定數量元素

  Stream 支持 skip(n) 方法,返回一個扔掉了前n個元素的流。如果流中元素不足n個,則返回一 個空流。

<code>        List<integer> skipAgeList = studentList.stream().map(s -> s.getAge())
.skip(2)
.collect(Collectors.toList());/<integer>/<code>

 7.映射


  • map
  • flatMap

  7.1 map

  Stream 支持 map 方法,它會接受一個函數作為參數。這個函數會被應用到每個元素上,並將其映 射成一個新的元素

<code>        List<integer> mapAageList = studentList.stream().map(s -> s.getAge())
.collect(Collectors.toList());/<integer>/<code>

  7.2 flatMap

  Stream 流支持 flatmap 方法讓你把一個流中的每個值都換成另一個流,然後把所有的流連接起來成為一個流

  注意 chars()方法返回的是IntStream ,需要裝箱 boxed,轉換為Stream,因為IntStream並不是Stream的子類

  下面的例子flatMap就是 分別把 前2個 student的name屬性轉換為一個流,並且將其合為一個流

<code>        List<integer> flatMapList = studentList.stream()
.limit(2)
.flatMap(s -> s.getName().chars().boxed())
.collect(Collectors.toList());/<integer>/<code>
<code>        flatMapList.stream().forEach(i -> System.out.println((char)i.intValue()));/<code>

 打印

<code>    j
o
h
n
n
y
c
a
n
d
y/<code>

 8.查找和匹配


  • anyMatch
  • allMatch
  • nonMatch
  • findAny
  • findFirst

  8.1 anyMatch

  流中是否有一個元素能匹配給定的謂詞,有則返回true 否則返回false。

<code>        //anyMatch 查找流中是否有滿足謂語的,存在就返回true 否則就返回false
boolean isExistAgeUp50 = studentList.stream()
.anyMatch(s -> s.getAge() > 50);/<code>

  8.2 allMatch

  流中是否有所有元素能匹配給定的謂詞。

<code>        boolean allMatchFlag = studentList.stream() 

.allMatch(s -> s.getAge() > 10);/<code>

  8.3 nonMatch

  流中是否有沒有任何元素能匹配給定的謂詞。

<code>        boolean noneMatchFlag =  studentList.stream()
.noneMatch(s -> s.getAge() > 100);/<code>

  8.4 findAny

  findAny 方法將返回當前流中的任意一個元素。注意在非並行流下大多情況返回第一個元素,但是不保證

<code>           Optional<student> studentOptional =  studentList.parallelStream()
.findAny();/<student>/<code>

  8.5 findFirst

  findFirst 方法將返回當前流中的第一個元素。


<code>         studentList.stream()
.map(s->s.getAge() * 2)
.filter(i -> i % 2==0)
.findFirst().ifPresent(i -> System.out.println(i));
/<code>

 9.歸約


  • reduce

 就是把一個流中的元素 經過lambda反覆進行操作,指到流被歸約成一個值

 reduce方法有3種形式:

Stream流的使用

 把一個流中的元素組合起來,使用 reduce 操作來表達更復雜的查 詢,比如“計算菜單中的總卡路里”或“菜單中卡路里最高的菜是哪一個”。此類查詢需要將流中所有元素反覆結合起來,得到一個值,比如一個Integer。這樣的查詢可以被歸類為歸約操作 (將流歸約成一個值)。

 reduce方法接受兩個參數:一個初始值,這裡是0;一個 BinaryOperator 來將兩個元素結合起來產生一個新值, 這裡我們用的是 lambda (a, b) -> a + b。


<code>      List<integer> nums = Arrays.asList(3, 4, 5, 6, 7);
int sum = nums.stream().reduce(0, (a, b) -> a + b);

/<integer>/<code>

 10.排序


  • sorted

 下面代碼以自然序排序一個list

<code>    list.stream().sorted()
/<code>

 自然序逆序元素,使用Comparator 提供的reverseOrder() 方法,前提是流中的元素要實現了Comparator接口,比如Integer 這種

<code>    list.stream().sorted(Comparator.reverseOrder())
/<code>

 使用Comparator 來排序一個list

<code>    list.stream().sorted(Comparator.comparing(Student::getAge))
/<code>

 把上面的元素逆序


<code>    list.stream().sorted(Comparator.comparing(Student::getAge).reversed())/<code>

 案例:將按照學生的Age屬性排序 和 倒序

<code>           studentList.stream() 

.sorted(Comparator.comparing(Student::getAge))
.forEach(System.out::println);/<code>
<code>        studentList.stream()
.sorted(Comparator.comparing(Student::getAge).reversed())
.forEach(System.out::println);
/<code>

 11.收集


  • collect

 將流元素進行中間操作後進行收集到一個List 或者Set 中去,結合Collectors的方法

<code>        studentList.stream()
.map(Student::getAge)
.collect(Collectors.toList());/<code>
<code>        studentList.stream()
.map(Student::getAge)
.collect(Collectors.toSet());

/<code>

 12.總結

 本篇主要講解JDK8中 Stream流的使用,流是什麼 如何創建 以及常用方法 包括如何 篩選 、切片、映射 、查找、匹配 、歸約 等等 每個類型都會有對應的案例 簡單易懂。

個人博客網站 https://www.askajohnny.com 歡迎訪問!

本文由博客一文多發平臺 https://openwrite.cn?from=article_bottom 發佈!


分享到:


相關文章: