搜尋
首頁Javajava教程Java8中Stream詳細用法歸納

本篇文章為大家帶來了關於java的相關知識,其中主要介紹了關於Stream詳細用法的相關問題,版本新增的Stream,配合約版本出現的Lambda ,給我們操作集合(Collection)提供了極大的便利,下面一起來看看,希望對大家有幫助。

Java8中Stream詳細用法歸納

推薦學習:《java影片教學

一、概述​​

Java 8 是一個非常成功的版本,這個版本新增的Stream,配合約版本出現的Lambda ,給我們操作集合(Collection)提供了極大的便利。 Stream流是JDK8新增的成員,允許以聲明性方式處理資料集合,可以把Stream流看作是遍歷資料集合的一個進階迭代器。 Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查找/篩選/過濾、排序、聚合和映射資料等操作。使用Stream API 對集合資料進行操作,就類似於使用 SQL 執行的資料庫查詢。也可以使用 Stream API 來並行執行操作。簡而言之,Stream API 提供了一種高效且易於使用的處理資料的方式。

1、使用流的好處

程式碼以宣告性方式書寫,說明想要完成什麼,而不是說明如何完成一個動作。
可以把幾個基礎操作連接起來,來表達複雜的資料處理的管線,同時保持程式碼清晰可讀。

2、流是什麼?

從支援資料處理操作的來源產生元素序列.資料來源可以是集合,陣列或IO資源。

從操作角度來看,流與集合是不同的. 流不儲存資料值; 流的目的是處理資料,它是關於演算法與計算的。

如果把集合當作流的資料來源,建立流時不會導致資料流動; 如果流的終止運算需要值時,流會從集合中取得值; 流只使用一次。

流中心思想是延遲計算,流直到需要時才計算值。
Java8中Stream詳細用法歸納
Stream可以由陣列或集合創建,對流的操作分為兩種:

#中間操作,每次傳回一個新的流,可以有多個。

終端機操作,每個流只能進行一次終端操作,終端操作結束後流無法再次使用。終端操作會產生一個新的集合或值。

特性:

不是資料結構,不會儲存資料。

不會修改原來的資料來源,它會將操作後的資料儲存到另一個物件中。 (保留意見:畢竟peek方法可以修改流中元素)

惰性求值,流在中間處理過程中,只是對操作進行了記錄,並不會立即執行,需要等到執行終止操作的時候才會進行實際的計算。

二、分類

Java8中Stream詳細用法歸納

無狀態:指元素的處理不受先前元素的影響;

有狀態:指該運算只有拿到所有元素之後才能繼續下去。

非短路運算:指必須處理所有元素才能得到最終結果;

短路運算:指遇到某些符合條件的元素就可以得到最終結果,如A || B,只要A為true,則無需判斷B的結果。

三、Stream的創建

Stream可以透過集合陣列來建立。

1、透過java.util.Collection.stream() 方法用集合建立流

List<string> list = Arrays.asList("a", "b", "c");// 创建一个顺序流
Stream<string> stream = list.stream();// 创建一个并行流
Stream<string> parallelStream = list.parallelStream();</string></string></string>

2、使用java.util.Arrays.stream(T[]array)方法用陣列建立流

int[] array={1,3,5,6,8};IntStream stream = Arrays.stream(array);

3、使用Stream的靜態方法:of()、iterate()、generate()

Stream<integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
 Stream<integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);stream2.forEach(System.out::println);
 Stream<double> stream3 = Stream.generate(Math::random).limit(3);stream3.forEach(System.out::println);</double></integer></integer>

輸出結果:

0 3 6 90.67961569092719940.19143142088542830.8116932592396652

stream和parallelStream的簡單區分:stream是順序流,由主執行緒依序對流執行操作,而parallelStream是並行流,內部以多執行緒並行執行的方式對流進行操作,但前提是流中的資料處理沒有順序要求。例如篩選集合中的奇數,兩者的處理不同之處:
Java8中Stream詳細用法歸納
如果流中的資料量夠大,並行流可以加快處速度。

除了直接建立並行流,還可以透過parallel()把順序流轉換成並行流:

Optional<integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();</integer>

四、Stream API簡介

在这里插入Java8中Stream詳細用法歸納描述
Java8中Stream詳細用法歸納

先贴上几个案例,水平高超的同学可以挑战一下:从员工集合中筛选出salary大于8000的员工,并放置到新的集合里。统计员工的最高薪资、平均薪资、薪资之和。将员工按薪资从高到低排序,同样薪资者年龄小者在前。将员工按性别分类,将员工按性别和地区分类,将员工按薪资是否高于8000分为两部分。用传统的迭代处理也不是很难,但代码就显得冗余了,跟Stream相比高下立判。

前提:員工類別

static List<person> personList = new ArrayList<person>();private static void initPerson() {
    personList.add(new Person("张三", 8, 3000));
    personList.add(new Person("李四", 18, 5000));
    personList.add(new Person("王五", 28, 7000));
    personList.add(new Person("孙六", 38, 9000));}</person></person>

1、遍歷/匹配(foreach/find/match)

Stream也是支援類似集合的遍歷和匹配元素的,只是Stream中的元素是以Optional類型存在的。 Stream的遍歷、配對非常簡單。

// import已省略,请自行添加,后面代码亦是
 
public class StreamTest {
  public static void main(String[] args) {
        List<integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
 
        // 遍历输出符合条件的元素
        list.stream().filter(x -> x > 6).forEach(System.out::println);
        // 匹配第一个
        Optional<integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
        // 匹配任意(适用于并行流)
        Optional<integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
        // 是否包含符合特定条件的元素
        boolean anyMatch = list.stream().anyMatch(x -> x <h3 id="按条件匹配filter">2、按条件匹配filter</h3>
<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/c32799257ddfee7ae65dfaf7bce4b27c-5.png?x-oss-process=image/resize,p_40" class="lazy" alt="在这里插入Java8中Stream詳細用法歸納描述"></p>
<p><strong>(1)筛选员工中已满18周岁的人,并形成新的集合</strong></p>
<pre class="brush:php;toolbar:false">/**
 * 筛选员工中已满18周岁的人,并形成新的集合
 * @思路
 * List<person> list = new ArrayList<person>();
 * for(Person person : personList) {
 *     if(person.getAge() >= 18) {
 *          list.add(person);
 *     }
 * }
 */
private static void filter01() {
    initPerson();
    List<person> collect = personList.stream().filter(x -> x.getAge()>=18).collect(Collectors.toList());
    System.out.println(collect);}</person></person></person>

在这里插入Java8中Stream詳細用法歸納描述
(2)自定义条件匹配
Java8中Stream詳細用法歸納

3、聚合max、min、count

Java8中Stream詳細用法歸納

(1)获取String集合中最长的元素

/**
 * 获取String集合中最长的元素
 * @思路
 * List<string> list = Arrays.asList("zhangsan", "lisi", "wangwu", "sunliu");
 * String max = "";
 * int length = 0;
 * int tempLength = 0;
 * for(String str : list) {
 *     tempLength = str.length();
 *     if(tempLength > length) {
 *         length  = str.length();
 *         max = str;
 *      }
 * }
 * @return zhangsan
 */
private static void test02() {
    List<string> list = Arrays.asList("zhangsan", "lisi", "wangwu", "sunliu");
    Comparator super String> comparator = Comparator.comparing(String::length);
    Optional<string> max = list.stream().max(comparator);
    System.out.println(max);}</string></string></string>

Java8中Stream詳細用法歸納
(2)获取Integer集合中的最大值

//获取Integer集合中的最大值
private static void test05() {
    List<integer> list = Arrays.asList(1, 17, 27, 7);
    Optional<integer> max = list.stream().max(Integer::compareTo);
    // 自定义排序
    Optional<integer> max2 = list.stream().max(new Comparator<integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    });
    System.out.println(max2);}</integer></integer></integer></integer>

Java8中Stream詳細用法歸納

//获取员工中年龄最大的人
private static void test06() {
    initPerson();
    Comparator super Person> comparator = Comparator.comparingInt(Person::getAge);
    Optional<person> max = personList.stream().max(comparator);
    System.out.println(max);}</person>

(3)获取员工中年龄最大的人
在这里插入Java8中Stream詳細用法歸納描述
4)计算integer集合中大于10的元素的个数
在这里插入Java8中Stream詳細用法歸納描述

4、map与flatMap

map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

Java8中Stream詳細用法歸納

(1)字符串大写
Java8中Stream詳細用法歸納
(2)整数数组每个元素+3

/**
 * 整数数组每个元素+3
 * @思路
 * List<integer> list = Arrays.asList(1, 17, 27, 7);
   List<integer> list2 = new ArrayList<integer>();
   for(Integer num : list) {
      list2.add(num + 3);
   }
   @return [4, 20, 30, 10]
 */
private static void test09() {
    List<integer> list = Arrays.asList(1, 17, 27, 7);
    List<integer> collect = list.stream().map(x -> x + 3).collect(Collectors.toList());
    System.out.println(collect);}</integer></integer></integer></integer></integer>

(3)公司效益好,每人涨2000

/**
 * 公司效益好,每人涨2000
 *
 */
private static void test10() {
    initPerson();
    List<person> collect = personList.stream().map(x -> {
        x.setAge(x.getSalary()+2000);
        return x;
    }).collect(Collectors.toList());
    System.out.println(collect);}</person>

(4)将两个字符数组合并成一个新的字符数组

/**
 * 将两个字符数组合并成一个新的字符数组
 *
 */
private static void test11() {
    String[] arr = {"z, h, a, n, g", "s, a, n"};
    List<string> list = Arrays.asList(arr);
    System.out.println(list);
    List<string> collect = list.stream().flatMap(x -> {
        String[] array = x.split(",");
        Stream<string> stream = Arrays.stream(array);
        return stream;
    }).collect(Collectors.toList());
    System.out.println(collect);}</string></string></string>

(5)将两个字符数组合并成一个新的字符数组

/**
 * 将两个字符数组合并成一个新的字符数组
 * @return [z,  h,  a,  n,  g, s,  a,  n]
 */
private static void test11() {
    String[] arr = {"z, h, a, n, g", "s, a, n"};
    List<string> list = Arrays.asList(arr);
    List<string> collect = list.stream().flatMap(x -> {
        String[] array = x.split(",");
        Stream<string> stream = Arrays.stream(array);
        return stream;
    }).collect(Collectors.toList());
    System.out.println(collect);}</string></string></string>

5、规约reduce

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。
Java8中Stream詳細用法歸納
(1)求Integer集合的元素之和、乘积和最大值

/**
 * 求Integer集合的元素之和、乘积和最大值
 *
 */
private static void test13() {
    List<integer> list = Arrays.asList(1, 2, 3, 4);
    //求和
    Optional<integer> reduce = list.stream().reduce((x,y) -> x+ y);
    System.out.println("求和:"+reduce);
    //求积
    Optional<integer> reduce2 = list.stream().reduce((x,y) -> x * y);
    System.out.println("求积:"+reduce2);
    //求最大值
    Optional<integer> reduce3 = list.stream().reduce((x,y) -> x>y?x:y);
    System.out.println("求最大值:"+reduce3);}</integer></integer></integer></integer>

(2)求所有员工的工资之和和最高工资

/*
 * 求所有员工的工资之和和最高工资
 */
private static void test14() {
    initPerson();
    Optional<integer> reduce = personList.stream().map(Person :: getSalary).reduce(Integer::sum);
    Optional<integer> reduce2 = personList.stream().map(Person :: getSalary).reduce(Integer::max);
    System.out.println("工资之和:"+reduce);
    System.out.println("最高工资:"+reduce2);}</integer></integer>

6、收集(toList、toSet、toMap)

取出大于18岁的员工转为map

/**
 * 取出大于18岁的员工转为map
 *
 */
private static void test15() {
    initPerson();
    Map<string> collect = personList.stream().filter(x -> x.getAge() > 18).collect(Collectors.toMap(Person::getName, y -> y));
    System.out.println(collect);}</string>

7、collect

Collectors提供了一系列用于数据统计的静态方法:

计数: count

平均值: averagingInt、 averagingLong、 averagingDouble

最值: maxBy、 minBy

求和: summingInt、 summingLong、 summingDouble

统计以上所有: summarizingInt、 summarizingLong、 summarizingDouble

/**
 * 统计员工人数、平均工资、工资总额、最高工资
 */
private static void test01(){
    //统计员工人数
    Long count = personList.stream().collect(Collectors.counting());
    //求平均工资
    Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
    //求最高工资
    Optional<integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
    //求工资之和
    Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
    //一次性统计所有信息
    DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
    System.out.println("统计员工人数:"+count);
    System.out.println("求平均工资:"+average);
    System.out.println("求最高工资:"+max);
    System.out.println("求工资之和:"+sum);
    System.out.println("一次性统计所有信息:"+collect);}</integer>

8、分组(partitioningBy/groupingBy)

分区:将stream按条件分为两个 Map,比如员工按薪资是否高于8000分为两部分。

分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。
Java8中Stream詳細用法歸納

将员工按薪资是否高于8000分为两部分;将员工按性别和地区分组

public class StreamTest {
  public static void main(String[] args) {
    personList.add(new Person("zhangsan",25, 3000, "male", "tieling"));
        personList.add(new Person("lisi",27, 5000, "male", "tieling"));
        personList.add(new Person("wangwu",29, 7000, "female", "tieling"));
        personList.add(new Person("sunliu",26, 3000, "female", "dalian"));
        personList.add(new Person("yinqi",27, 5000, "male", "dalian"));
        personList.add(new Person("guba",21, 7000, "female", "dalian"));
 
    // 将员工按薪资是否高于8000分组
        Map<boolean>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
        // 将员工按性别分组
        Map<string>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        // 将员工先按性别分组,再按地区分组
        Map<string>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
        System.out.println("员工按薪资是否大于8000分组情况:" + part);
        System.out.println("员工按性别分组情况:" + group);
        System.out.println("员工按性别、地区:" + group2);
  }}</string></string></boolean>

9、连接joining

joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。
Java8中Stream詳細用法歸納

10、排序sorted

将员工按工资由高到低(工资一样则按年龄由大到小)排序

private static void test04(){
    // 按工资升序排序(自然排序)
    List<string> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
            .collect(Collectors.toList());
    // 按工资倒序排序
    List<string> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
            .map(Person::getName).collect(Collectors.toList());
    // 先按工资再按年龄升序排序
    List<string> newList3 = personList.stream()
            .sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
            .collect(Collectors.toList());
    // 先按工资再按年龄自定义排序(降序)
    List<string> newList4 = personList.stream().sorted((p1, p2) -> {
        if (p1.getSalary() == p2.getSalary()) {
            return p2.getAge() - p1.getAge();
        } else {
            return p2.getSalary() - p1.getSalary();
        }
    }).map(Person::getName).collect(Collectors.toList());
 
    System.out.println("按工资升序排序:" + newList);
    System.out.println("按工资降序排序:" + newList2);
    System.out.println("先按工资再按年龄升序排序:" + newList3);
    System.out.println("先按工资再按年龄自定义降序排序:" + newList4);}</string></string></string></string>

11、提取/组合

流也可以进行合并、去重、限制、跳过等操作。

private static void test05(){
    String[] arr1 = { "a", "b", "c", "d" };
    String[] arr2 = { "d", "e", "f", "g" };
    Stream<string> stream1 = Stream.of(arr1);
    Stream<string> stream2 = Stream.of(arr2);
    // concat:合并两个流 distinct:去重
    List<string> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
    // limit:限制从流中获得前n个数据
    List<integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
    // skip:跳过前n个数据
    List<integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());
 
    System.out.println("流合并:" + newList);
    System.out.println("limit:" + collect);
    System.out.println("skip:" + collect2);}</integer></integer></string></string></string>

12、读取文件的流操作

Java8中Stream詳細用法歸納

13、计算两个list中的差集

//计算两个list中的差集
List<string> reduce1 = allList.stream().filter(item -> !wList.contains(item)).collect(Collectors.toList());</string>

推荐学习:《java视频教程

以上是Java8中Stream詳細用法歸納的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:CSDN。如有侵權,請聯絡admin@php.cn刪除
如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?Mar 17, 2025 pm 05:46 PM

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?Mar 17, 2025 pm 05:44 PM

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?Mar 17, 2025 pm 05:43 PM

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Mar 17, 2025 pm 05:35 PM

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),