1. 程式人生 > >JDK 1.8 新特性之Stream 詳解個人筆記

JDK 1.8 新特性之Stream 詳解個人筆記

雖然java 10已經發布,11 已經在路上,雖然 java EE 已經更名為 jakarta EE,但是大多數人連jdk1.8的新特性都不太瞭解,本人也是如此,所以在學習Java 8 API 新增的 Stream 的時候 做一些個人筆記,希望幫助自己的同時也能幫到大家。

首先對stream的操作可以分為兩類,中間操作(intermediate operations)和結束操作(terminal operations):

  • 中間操作總是會惰式執行,呼叫中間操作只會生成一個標記了該操作的新stream。
  • 結束操作會觸發實際計算,計算髮生時會把所有中間操作積攢的操作以pipeline的方式執行,這樣可以減少迭代次數。計算完成之後stream就會失效。

雖然大部分情況下stream是容器呼叫Collection.stream()方法得到的,但stream和collections有以下不同:

  • 無儲存。stream不是一種資料結構,它只是某種資料來源的一個檢視,資料來源可以是一個數組,Java容器或I/O channel等。
  • 為函數語言程式設計而生。對stream的任何修改都不會修改背後的資料來源,比如對stream執行過濾操作並不會刪除被過濾的元素,而是會產生一個不包含被過濾元素的新stream。
  • 惰式執行。stream上的操作並不會立即執行,只有等到使用者真正需要結果的時候才會執行。
  • 可消費性。stream只能被“消費”一次,一旦遍歷過就會失效,就像容器的迭代器那樣,想要再次遍歷必須重新生成。

一、獲取stream

    // 1、陣列
    String[] arr = new String[]{"ab", "cd", "ef"};
    Stream<String> arrStream = Arrays.stream(arr);
    // 2、集合
    List<String> list = Arrays.asList("ab", "cd", "ef");
    Stream<String> colStream = list.stream();
    // 3、值
    Stream<String> stream = Stream.of("ab", "cd", "ef");

二、stream方法使用

測試資料:

  List<User> list = Arrays.asList(
     // name,age
      new User("張三", 11),
      new User("王五", 20),
      new User("王五", 91),
      new User("張三", 8),
      new User("李四", 44),
      new User("李四", 44),
      new User("李四", 44)
  );

1、forEach() 使用該方法迭代流中的每個資料

  /**
   * forEach 迭代輸出每條資料.
   */
  @Test
  public void testForEach(){
    // java 8 前
    System.out.println("java 8 前");
    for(User user: list){
      System.out.println(user);
    }
    // java 8 lambda
    System.out.println("java 8 lambda");
    list.forEach(user -> System.out.println(user));

    // java 8 stream lambda
    System.out.println("java 8 stream lambda");
    list.stream().forEach(user -> System.out.println(user));
  }

console->

2、sorted() 使用該方法排序資料

  /**
   * sort 排序.
   */
  @Test
  public void testSort() {
    System.out.println("-----排序前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----排序後-----");
    // java 8 前
    System.out.println("java 8 前");
    Collections.sort(list, new Comparator<User>() {
      @Override
      public int compare(User o1, User o2) {
        return o1.getAge().compareTo(o2.getAge());
      }
    });
    for (User user : list) {
      System.out.println(user);
    }
    // java 8 stream 方法引用
    System.out.println("java 8 stream 方法引用");
    list.stream().sorted(Comparator.comparing(User::getAge)).forEach(user -> System.out.println(user));
  }

console->

3、filter():使用該方法過濾

  /**
   * filter 過濾.
   */
  @Test
  public void testFilter() {
    // 輸出年齡大於50的人
    System.out.println("-----過濾前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----過濾後-----");
    // java 8 前
    System.out.println("java 8 前");
    for(User user: list){
      if (user.getAge() > 50) {
        System.out.println(user);
      }
    }
    // java 8 stream
    System.out.println("java 8 stream");
    list.stream().filter((User user) -> user.getAge() > 50).forEach(user -> System.out.println(user));
  }

console->

4、limit():使用該方法截斷

  /**
   * limit 截斷.
   */
  @Test
  public void testLimit() {
    // 從第三個開始截斷,只輸出前三個
    System.out.println("-----截斷前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----截斷後-----");
    // java 8 前
    System.out.println("java 8 前");
    for (int i = 0; i < 3; i++) {
      System.out.println(list.get(i));
    }
    // java 8 stream
    System.out.println("java 8 stream");
    list.stream().limit(3).forEach(user -> System.out.println(user));
  }

console->

5、skip():與limit互斥,使用該方法跳過元素

  /**
   * skip 跳過.
   */
  @Test
  public void testSkip() {
    // 跳過前三個元素,從第四個開始輸出
    System.out.println("-----跳過前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----跳過後-----");
    // java 8 前
    System.out.println("java 8 前");
    for (int i = 3; i < list.size(); i++) {
      System.out.println(list.get(i));
    }
    // java 8 stream
    System.out.println("java 8 stream");
    list.stream().skip(3).forEach(user -> System.out.println(user));
  }

console->

6、distinct():使用該方法去重,注意:必須重寫對應泛型的hashCode()和equals()方法

  /**
   * distinct 去重.
   */
  @Test
  public void testDistinct() {
    // 因為Arrays.asList() 返回的是Arrays的內部類ArrayList,操作remove,add會報錯
    List<User> users = new ArrayList(list);
    // 為list去除重複資料
    System.out.println("-----去重前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----去重後-----");
    // java 8 前
    System.out.println("java 8 前");
    for (int i = 0; i < users.size() - 1; i++) {
      for (int j = users.size() - 1; j > i; j--) {
        if (users.get(j).getAge() == users.get(i).getAge() && users.get(j).getName()
            .equals(users.get(i).getName())) {
          users.remove(i);
        }
      }
    }
    for (User user : users) {
      System.out.println(user);
    }
    // java 8 stream
    System.out.println("java 8 stream");
    users.stream().distinct().forEach(user -> System.out.println(user));
  }

console->

***根據上述方法,完成去重+按照年齡大於40以後從小到大+只取前二

  /**
   * 去重+按照年齡大於40以後從小到大+只取前二
   */
  @Test
  public void demo() {
    list.stream().distinct().filter(user -> user.getAge() > 40).sorted(
        Comparator.comparing(User::getAge)).limit(2).forEach(user -> System.out
        .println(user));
  }

console->

7、max,min,sum,avg,count 

  /**
   * 測試計算.
   */
  @Test
  public void testNum() {
    IntSummaryStatistics num = list.stream().mapToInt(u -> u.getAge())
        .summaryStatistics();
    System.out.println("總共人數:" + num.getCount());
    System.out.println("平均年齡:" + num.getAverage());
    System.out.println("最大年齡:" + num.getMax());
    System.out.println("最小年齡:" + num.getMin());
    System.out.println("年齡之和:" + num.getSum());
  }

console->

8、map():接收一個方法作為引數,該函式會被應用到每個元素上,並將其對映成一個新的元素

  /**
   * map 對映.
   */
  @Test
  public void testMap() {
    // 只輸出所有人的年齡
    list.stream().forEach(user -> System.out.println(user));
    System.out.println("對映後----->");
    List<Integer> ages = list.stream().map(user -> user.getAge()).collect(toList());
    ages.forEach(age -> System.out.println(age));

    // 小寫轉大寫
    List<String> words = Arrays.asList("aaa", "vvvv", "cccc");
    System.out.println("全部大寫---->");
    List<String> collect = words.stream().map(s -> s.toUpperCase()).collect(toList());
    collect.forEach(s -> System.out.println(s));
  }

console->

9、flatMap():對每個元素執行mapper指定的操作,並用所有mapper返回的Stream中的元素組成一個新的Stream作為最終返回結果,通俗易懂就是將原來的stream中的所有元素都展開組成一個新的stream

 /**
   * flatMap .
   */
  @Test
  public void testFlatMap() {
    //建立一個 裝有兩個泛型為integer的集合
    Stream<List<Integer>> stream = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5));
    // 將兩個合為一個
    Stream<Integer> integerStream = stream.flatMap(
        (Function<List<Integer>, Stream<Integer>>) integers -> integers.stream());
    // 為新的集合
    List<Integer> collect = integerStream.collect(toList());
    System.out.println("新stream大小:"+collect.size());
    System.out.println("-----合併後-----");
    collect.forEach(o -> System.out.println(o));
  }

console->

10、findFirst() :使用該方法獲取第一個元素

  /**
   * findFirst 獲取第一個元素.
   */
  @Test
  public void testFindFirst(){
    User user = list.stream().findFirst().get();
    System.out.println(user);
  }

console->

相關推薦

JDK 1.8 特性Stream 個人筆記

雖然java 10已經發布,11 已經在路上,雖然 java EE 已經更名為 jakarta EE,但是大多數人連jdk1.8的新特性都不太瞭解,本人也是如此,所以在學習Java 8 API 新增的 Stream 的時候 做一些個人筆記,希望幫助自己的同時也能幫到大家。

jdk 1.8 特性——stream Collectors

Collectors的倆個作用:           1、將資料流縮減為一個單一值,可以是一個collection、基本資料型別或者一個自定義物件;          2、將資料流中的元素進行分組,根據任務型別將流中所有的任務進行分組。這將產生一個Map<TaskTyp

JDK 1.8 特性Lambda表示式

Lambda表示式基礎 Lambda表示式【Lambda Expressions】也可稱為閉包,是推動 Java 8 釋出的最重要新特性。Lambda 允許把函式作為一個方法的引數(函式作為引數傳遞進方法中),使用 Lambda 表示式可以使程式碼變的更加

Java8特性Stream

       最近在公司的專案中常用Stream結合Lambda表示式來操作集合,使得專案整體程式碼簡潔和整齊;並且上一章也講了一些關於Stream的常用操作,比如:map()、filter()、concat()、reduce()、max()、min()、

Java8特性Stream

寫了Lambda表示式的部落格,怎麼能少了對Stream的學習呢!接下來就將我所理解的Stream分享給大家,歡迎指出不足之處... 一、為什麼要使用Stream?Stream是什麼?在Java中該怎麼用呢?        (1)為什麼要使用Str

JDK 1.5 特性列舉,舉例說明

對於比較穩定的值集合,Java 提供了列舉來定義,簡單舉例如下: package com.jalor; public class HomeWork { enum Weeks { MON() { @Override publ

java 8 特性Stream的排序/分類

  Stream簡介 Stream是Java8提供的一個新的API,它位於java.util.stream包下。Stream API提供了一種新的方式來對Java集合進行操作,這種操作方式極大的提高了Java程式設計師的生產力,讓程式設計師寫出高效率、乾淨、簡潔的程式碼。我們可以將元素集合看作一

JDK 1.7 特性在數字字面量使用下劃線

轉自:https://blog.csdn.net/heartroll/article/details/78455045#%E5%9C%A8%E6%95%B0%E5%AD%97%E5%AD%97%E9%9D%A2%E9%87%8F%E4%BD%BF%E7%94%A8%E4%B8%8B%E5%88%92

跟我學 Java 8 特性 Stream 流(四)並行流

隨著對流API認識的慢慢深入,本章我們要討論的知識點是流API裡面的並行流了。 在開始討論並行流之前,我先引發一下大家的思考,就你看到這篇文章的時間,你們是不是經常聽到,Intel i7 CPU什麼8核16執行緒,什麼Android手機8核4GB這種訊息,既然我們是處於

跟我學 Java 8 特性 Stream 流(三)縮減操作

和前面兩篇文章一起服用,效果會更佳。通過對流API的基礎體驗Demo和關鍵知識點的講解,相信大家對流API都有一定的認識了,但是流API強大的功能,可不僅僅像前面兩篇文章中說的那樣簡單,大家應該注意到,在第二篇中,我對Stream介面進行介紹的時候,並沒有把他的全部方法都

跟我學 Java 8 特性 Stream 流(二)關鍵知識點

我們的第一篇文章,主要是通過一個Demo,讓大家體驗了一下使用流API的那種酣暢淋漓的感覺。如果你沒有實踐,我還是再次呼籲你動手敲一敲,自己實實在跑一遍上一篇的Demo。 相信你的感受和理解也會隨之加深的。繼續探索流API的高階功能之前,我們先從介面級別全面瞭解一下流A

跟我學 Java 8 特性 Stream 流基礎體驗

Java8新增的功能中,要數lambda表示式和流API最為重要了.這篇文章主要介紹流API的基礎,也是流API系列的第一篇文章,話不多說,直奔主題. 什麼是流API? 它能做一些什麼? 我們應該知道(絕對知道~)API是一個程式向使用者提供的一些方法,通過這些方法就

1.8 特性 Lambda Expressions

Lambda expressions are allowed only at source level 1.8 or above The target type of this expression must be a functional interface   https://docs.o

跟我學 Java 8 特性 Stream 流(六)收集

我們前面的五篇文章基本都是在說將一個集合轉成一個流,然後對流進行操作,其實這種操作是最多的,但有時候我們也是需要從流中收集起一些元素,並以集合的方式返回,我們把這種反向操作稱為收集。 流API也給我們提供了相應的方法。 如何在流中使用收集功能? 我們先看一看流API

跟我學 Java 8 特性 Stream 流(七)流與迭代器,流系列大結局

恭喜你們,馬上就要學完Java8 Stream流的一整系列了,其實我相信Stream流對很多使用Java的同學來說,都是一個知識盲點,因為這個原因,我才這麼細緻地講解Stream流的各個知識點,通過這一整個系列,我相信只要認真看了的同學,都已掌握的差不多了,就差實戰了。

JDK 1.8特性Lambda入門

轉載至:https://blog.csdn.net/chenchaofuck1/article/details/51897481 網上關於java lambda的例子很多,但是這些五花八門的例子很不常見不常用,最後導致初學者望而卻步,其實我們抓住lambda的本質之後,會發現lambda還是

Open JDK 7 特性(即JDK 1.8 特性)

Summary Features are listed in order, more or less, from lowest to highest in the overall JDK  software stack. Features that were onc

Go 1.9 特性 Type Alias type MyInt2 = int

Go 1.9 新特性 Type Alias 詳解 飛雪無情 2017 年 8 月 28 日 話題:語言 & 開發架構Go 北京時間 2017.08.25,Go1.9 正式版釋出了。Go1.9 經歷了 2 個 beta,好幾個月,終於定了,釋出了正式版本。Go 1.9

Java8特性Optional

Java8中對空值提供了一個操作類。Optional。下面介紹下他的方法。 靜態方法: Optional.of(T)    返回Optional包裹的物件,如果傳入的引數為空,將丟擲空指標異常。 Optional.ofNullable(T) 返回Optional包裹的物件

Go 1.9 特性 Type Alias

北京時間2017.08.25,Go1.9正式版釋出了。Go1.9經歷了2個beta,好幾個月,終於定了,釋出了正式版本。Go 1.9包含了很多改變,比如類型別名Type Alias,安全併發Map,並行編譯等,都是很大的改變,今天這篇文章主要介紹類型別名 Type Ali