欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中l(wèi)ist.foreach()和list.stream().foreach()用法詳解

 更新時間:2024年07月05日 11:23:33   作者:碼農(nóng)研究僧  
在Java中List是一種常用的集合類,用于存儲一組元素,List提供了多種遍歷元素的方式,包括使用forEach()方法和使用Stream流的forEach()方法,這篇文章主要給大家介紹了關(guān)于Java中l(wèi)ist.foreach()和list.stream().foreach()用法的相關(guān)資料,需要的朋友可以參考下

前言

典故來源于項目中使用了兩種方式的foreach,后面嘗試體驗下有何區(qū)別!

先看代碼示例:

使用List的forEach

import java.util.Arrays;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> data = Arrays.asList("One", "Two", "Three", "Four", "Five");

        // 使用List的forEach
        data.forEach(element -> {
            System.out.println("Element: " + element);
        });
    }
}

使用Stream API的forEach

import java.util.Arrays;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> data = Arrays.asList("One", "Two", "Three", "Four", "Five");

        // 使用Stream API的forEach
        data.stream().forEach(element -> {
            System.out.println("Element: " + element);
        });
    }
}

兩者輸出結(jié)果都為如下:

既然兩個都輸出差不多的結(jié)果,但兩者還是稍微有些小區(qū)別,具體看下文!

1. 基本知識

  • forEach() 是List接口的一部分,用于對列表中的每個元素執(zhí)行給定的操作。與Stream API的 forEach 不同,list的 forEach 不支持并行處理,因此它在處理大量數(shù)據(jù)時可能不如Stream API高效。
    適用于簡單的迭代和操作,不需要復(fù)雜的流處理。

  • stream().forEach() 是Stream API的一部分,用于對流中的每個元素執(zhí)行給定的操作。使用Stream API的 forEach 允許進行更多的操作,例如過濾、映射等,因為你可以在流上鏈式調(diào)用其他方法。
    Stream API提供了更多的靈活性和功能,適用于處理大量數(shù)據(jù)或進行復(fù)雜的操作。

兩者更多的區(qū)別可看下表:

代碼塊概念作用差異之處適用場景
list.foreach()List接口中的方法,用于對列表中的每個元素執(zhí)行給定的操作1.通過 forEach(),可以對列表中的每個元素進行遍歷,并在每個元素上執(zhí)行指定的操作。

2.主要用于簡單的迭代和操作,適用于不需要復(fù)雜流處理的場景。
1.并行處理: List的 forEach 不支持并行處理,因此在處理大量數(shù)據(jù)時可能不如Stream API高效。Stream API的并行處理機制可以更好地利用多核處理器的性能。

2.功能限制: List的 forEach 主要用于簡單的迭代操作,而沒有提供像Stream API那樣的豐富中間操作和終端操作,限制了其在復(fù)雜數(shù)據(jù)處理場景中的應(yīng)用。
適用于簡單的遍歷和操作,例如對列表中的元素進行打印、計算簡單統(tǒng)計量等。

不適用于需要復(fù)雜處理邏輯的情況。
stream().foreach()Java 8引入的Stream API中的方法,用于對流中的每個元素執(zhí)行給定的操作。1.通過 forEach(),可以對流中的每個元素進行遍歷,并在每個元素上執(zhí)行指定的操作。

2.Stream API提供了一種更為函數(shù)式的方式來處理數(shù)據(jù),允許鏈式調(diào)用其他方法,如過濾、映射、排序等。
1.鏈式調(diào)用: 使用Stream API的 forEach 允許在流上進行鏈式調(diào)用其他方法,使得可以進行更多的操作。這種鏈式調(diào)用是函數(shù)式編程的一種特征,使代碼更為靈活和表達性強。

2.功能豐富: Stream API提供了更多的中間操作和終端操作,例如 map、filter、reduce 等,這些操作可以組合使用,實現(xiàn)更復(fù)雜的數(shù)據(jù)處理邏輯。
適用于處理大量數(shù)據(jù)或進行復(fù)雜的操作,例如對數(shù)據(jù)進行變換、過濾、聚合等。

Stream API的并行處理機制也使得在多核處理器上能夠更高效地處理大規(guī)模數(shù)據(jù)。

總結(jié):

2. 差異之處

此處的差異之處主要講解stream().foreach() 比 list.foreach()多的點

2.1 執(zhí)行順序

stream流中如果結(jié)合parallelStream(),會有不一樣的特性!

import java.util.Arrays;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> data = Arrays.asList("One", "Two", "Three", "Four", "Five");

        // 使用Stream API中的parallelStream  forEach
        data.parallelStream().forEach(element -> {
            System.out.println("Element: " + element);
        });
    }
}

截圖如下:

在使用 parallelStream() 進行并行處理時,元素的處理順序可能不會按照原始列表中的順序輸出。
并行流會將數(shù)據(jù)分成多個塊,然后并行處理這些塊,最后將結(jié)果合并。

因此,并行處理的結(jié)果可能在不同的塊之間交錯,導(dǎo)致輸出的順序不再按照原始列表的順序。

想要保持順序,可以使用 forEachOrdered() 方法,它會保證按照流的遍歷順序輸出結(jié)果(并行流的情況下保持元素的遍歷順序,但可能會犧牲一些并行處理的性能優(yōu)勢)。示例如下:

import java.util.Arrays;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> data = Arrays.asList("One", "Two", "Three", "Four", "Five");

        // 使用Stream API的parallelStream().forEachOrdered
        data.parallelStream().forEachOrdered(element -> {
            System.out.println("Element: " + element);
        });
    }
}

截圖如下:

2.2 串行并行

對應(yīng)上章節(jié)繼續(xù)科普parallelStream(),一般來說并行的輸出速度比較快,用于對順序輸出不講究,但是大量的數(shù)據(jù)處理可以用這個!

對于少量的數(shù)據(jù)來說,效果不明顯,甚至會高于list.foreach(),所以根據(jù)情況而來,一般數(shù)據(jù)處理多,可以應(yīng)用parallelStream()

import java.util.ArrayList;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        for (int i = 1; i <= 1000000; i++) {
            numbers.add(i);
        }

        // 使用 Stream.forEach 進行并行處理
        long startTime = System.currentTimeMillis();

        numbers.parallelStream().forEach(element -> {
            // 模擬一些耗時的操作
            Math.pow(element, 2);
        });

        long endTime = System.currentTimeMillis();
        System.out.println("Time taken with Stream.forEach (parallel): " + (endTime - startTime) + " ms");
    }
}

截圖如下所示:

原本以為使用list.foreach(),時間會更長,反而時間更短:

import java.util.ArrayList;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        for (int i = 1; i <= 1000000; i++) {
            numbers.add(i);
        }

        // 使用 List.forEach 進行串行處理
        long startTime = System.currentTimeMillis();

        numbers.forEach(element -> {
            // 模擬一些耗時的操作
            Math.pow(element, 2);
        });

        long endTime = System.currentTimeMillis();
        System.out.println("Time taken with List.forEach (sequential): " + (endTime - startTime) + " ms");
    }
}

截圖如下:

可能是由于數(shù)據(jù)規(guī)模較小、并行處理帶來的額外開銷以及模擬的耗時操作較短,導(dǎo)致并行流的性能沒有得到有效提升。

并行處理的優(yōu)勢在于處理大規(guī)模數(shù)據(jù)時更為顯著。

2.3 復(fù)雜數(shù)據(jù)處理

Stream API提供了豐富的中間操作和終端操作,使得能夠進行更復(fù)雜的數(shù)據(jù)處理。

下面舉例說明 filter()、map()、reduce() 這幾個常用的操作方法。

  • filter() 用于對流中的元素進行過濾,只保留滿足某個條件的元素:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Demo {
    public static void main(String[] args) {
        List<String> data = Arrays.asList("One", "Two", "Three", "Four", "Five");

        // 過濾出長度大于3的元素
        List<String> filteredList = data.stream()
                .filter(element -> element.length() > 3)
                .collect(Collectors.toList());

        System.out.println("Filtered List: " + filteredList);
    }
}

截圖如下:

  • map() 用于對流中的每個元素進行映射轉(zhuǎn)換,生成一個新的流:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Demo {
    public static void main(String[] args) {
        List<String> data = Arrays.asList("One", "Two", "Three", "Four", "Five");

        // 將每個元素轉(zhuǎn)換為大寫
        List<String> uppercasedList = data.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());

        System.out.println("Uppercased List: " + uppercasedList);
    }
}

截圖如下:

  • reduce() 用于將流中的元素逐個進行操作,最終得到一個結(jié)果
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Demo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 對所有元素求和
        Optional<Integer> sum = numbers.stream()
                .reduce((x, y) -> x + y);
        
        sum.ifPresent(result -> System.out.println("Sum: " + result));
    }
}

使用 Optional<Integer> 主要是為了處理可能沒有元素的情況,避免返回 null。

考慮到 numbers 可能為空,如果直接使用 reduce((x, y) -> x + y),當 numbers 為空時,會得到 null,而這可能導(dǎo)致空指針異常。

截圖如下:

拓展1

對于上述代碼中,都有使用到Collectors.toList()

Collectors.toList() 是Collectors 工具類提供的一個靜態(tài)方法,它用于將流中的元素收集到一個 List 集合中。
在Stream API中,對流進行一系列的操作后,通常會希望將結(jié)果收集到一個集合中,以便后續(xù)的操作或輸出。

在實際應(yīng)用中,還可以使用其他的 Collectors 方法,如 toSet()、toMap() 等,以便根據(jù)需求將元素收集到不同的集合類型中。

拓展2

對于上述reduce中,使用到了Optional 

Optional 是Java 8引入的一個類,用于處理可能為null的值。
它的設(shè)計目的是避免使用null,減少空指針異常的發(fā)生,并提供更安全、清晰的代碼。

在上述代碼中,通過使用 Optional<Integer>,可以更安全地處理可能為空的情況。如果 numbers 為空,reduce 操作的結(jié)果將是 Optional.empty(),而不是 null。

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class ReduceWithOptionalExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用Optional處理可能為空的情況
        Optional<Integer> sum = numbers.stream()
                .reduce((x, y) -> x + y);

        // 判斷Optional是否包含值
        if (sum.isPresent()) {
            System.out.println("Sum: " + sum.get());
        } else {
            System.out.println("The list is empty.");
        }
    }
}

2.4 CRUD集合

當使用 list.foreach() 或 stream().foreach() 進行遍歷操作時,如果在遍歷過程中對集合進行了增、刪、改的操作,可能會導(dǎo)致 ConcurrentModificationException 異常。

一、list.foreach()的增刪:

增加數(shù)據(jù)的Demo代碼:

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List<String> data = new ArrayList<>();
        data.add("One");
        data.add("Two");
        data.add("Three");

        // 使用 List.forEach 遍歷,并在遍歷過程中增加元素
        data.forEach(element -> {
            System.out.println("Element: " + element);
            if (element.equals("Two")) {
                data.add("Four"); // 在遍歷過程中增加元素
            }
        });
    }
}

以及刪除數(shù)據(jù)Demo:

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List<String> data = new ArrayList<>();
        data.add("One");
        data.add("Two");
        data.add("Three");

        // 使用 List.forEach 遍歷,并在遍歷過程中刪除元素
        data.forEach(element -> {
            System.out.println("Element: " + element);
            if (element.equals("Two")) {
                data.remove(element); // 在遍歷過程中刪除元素,可能導(dǎo)致異常
            }
        });
    }
}

最終的結(jié)果截圖如下:

二、list.stream().foreach()的增刪:

增加數(shù)據(jù)的Demo代碼:

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List<String> data = new ArrayList<>();
        data.add("One");
        data.add("Two");
        data.add("Three");

        // 使用 Stream.forEach 遍歷,并在遍歷過程中增加元素
        data.stream().forEach(element -> {
            System.out.println("Element: " + element);
            if (element.equals("Two")) {
                data.add("Four"); // 在遍歷過程中增加元素
            }
        });
    }
}

截圖如下:

以及刪除數(shù)據(jù)Demo:

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List<String> data = new ArrayList<>();
        data.add("One");
        data.add("Two");
        data.add("Three");

        // 使用 Stream.forEach 遍歷,并在遍歷過程中刪除元素
        data.stream().forEach(element -> {
            System.out.println("Element: " + element);
            if (element.equals("Two")) {
                data.remove(element); // 在遍歷過程中刪除元素,可能導(dǎo)致異常
            }
        });
    }
}

截圖如下:

通過上述四個程序的執(zhí)行結(jié)果,可以得到什么體會呢???

stream().foreach()在操作集合的CRUD的時候,執(zhí)行錯誤之后,還是會迭代整個列表,才看到異常

這也證明stream().foreach()為并行執(zhí)行處理數(shù)據(jù),而不是串行

那有辦法解決這種異常的情況么,又能對集合進行CRUD?。ù鸢甘怯械?,可看如下正文)

2.5 迭代器

通過上述的閱讀,急需需要一個對集合的CRUD做一個安全性的迭代!
于是有了如下的解決方式:

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List<String> data = new ArrayList<>();
        data.add("One");
        data.add("Two");
        data.add("Three");

        // 使用迭代器遍歷,并在條件滿足時刪除元素
        Iterator<String> iterator = data.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println("Element: " + element);
            if (element.equals("Two")) {
                iterator.remove(); // 嘗試在不支持結(jié)構(gòu)性修改的列表上進行刪除操作,拋出異常
            }
        }

        System.out.println("Modified List: " + data);
    }
}

截圖如下:

3. 總結(jié)

總結(jié)起來,對于上面的代碼學習,主要涉及了兩種遍歷集合的方式:List.forEach() 和 List.stream().forEach()。下面對這兩種方式的區(qū)別進行總結(jié):

List.forEach() 方法:

  • 遍歷是在當前線程中按順序執(zhí)行的,對集合元素的操作是同步的。

  • 適用于簡單的、順序執(zhí)行的遍歷操作。

  • 不支持并行操作,不保證源數(shù)據(jù)的順序。

List.stream().forEach() 方法:

  • 可以利用并行流進行多線程處理,提高遍歷效率,不保證源數(shù)據(jù)的順序。

  • 適用于更復(fù)雜的、并行處理的遍歷操作,可以配合 Stream 的其他操作進行更靈活的數(shù)據(jù)處理。

4. 彩蛋

對于上述中的代碼,有一個需要注意的點:
不管是list.foreach()還是list.stream().foreach(),集合的CRUD都會出現(xiàn)會爆:Exception in thread "main" java.lang.UnsupportedOperationException的錯誤,舉一個例子。

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List<String> data = Arrays.asList("One", "Two", "Three");

        // 使用 List.forEach 遍歷,并在遍歷過程中刪除元素
        data.forEach(element -> {
            System.out.println("Element: " + element);
            if (element.equals("Two")) {
                data.remove(element); // 在遍歷過程中刪除元素,可能導(dǎo)致異常
            }
        });
    }
}

截圖如下:

主要的原因在于:

Arrays.asList("One", "Two", "Three", "Four", "Five") 創(chuàng)建的列表是由數(shù)組支持的固定大小的列表。

這意味著該列表不支持結(jié)構(gòu)性修改操作(如添加、刪除),并且會在嘗試進行這些操作時拋出UnsupportedOperationException 異常。

到此這篇關(guān)于Java中l(wèi)ist.foreach()和list.stream().foreach()用法詳解的文章就介紹到這了,更多相關(guān)Java中l(wèi)ist.foreach()和list.stream().foreach()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot 配置隨機數(shù)的技巧代碼詳解

    Spring Boot 配置隨機數(shù)的技巧代碼詳解

    這篇文章主要介紹了Spring Boot 配置隨機數(shù)技巧,spring boot 支持在系統(tǒng)加載的時候配置隨機數(shù),具體實例代碼大家參考下本文
    2018-05-05
  • java為何不能多繼承的原因詳解

    java為何不能多繼承的原因詳解

    多重繼承是一個子類從多個父類中繼承屬性和方法。C++, Common Lisp是時下支持多重繼承的流行語言。那java為何不能多繼承呢,下面小編帶大家來一起學習一下吧
    2019-06-06
  • SpringBoot實現(xiàn)使用反射模擬IOC和getBean

    SpringBoot實現(xiàn)使用反射模擬IOC和getBean

    這篇文章主要介紹了SpringBoot實現(xiàn)使用反射模擬IOC和getBean,IOC就是spring的核心思想之一——控制反轉(zhuǎn)。這里不再贅述,看此文章即可了解
    2023-04-04
  • jvm排查工具箱jvm-tools下載使用詳解

    jvm排查工具箱jvm-tools下載使用詳解

    這篇文章主要為大家介紹了jvm排查工具箱jvm-tools下載使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • spring boot 日志/頁面處理、實體類構(gòu)建、后臺管理功能的實現(xiàn)

    spring boot 日志/頁面處理、實體類構(gòu)建、后臺管理功能的實現(xiàn)

    這篇文章主要介紹了spring boot 日志/頁面處理、實體類構(gòu)建、后臺管理功能的實現(xiàn),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • Java?常量池詳解之字符串常量池實現(xiàn)代碼

    Java?常量池詳解之字符串常量池實現(xiàn)代碼

    這篇文章主要介紹了Java?常量池詳解之字符串常量池,本文結(jié)合示例代碼對java字符串常量池相關(guān)知識講解的非常詳細,需要的朋友可以參考下
    2022-12-12
  • Java網(wǎng)絡(luò)編程之IO模型阻塞與非阻塞簡要分析

    Java網(wǎng)絡(luò)編程之IO模型阻塞與非阻塞簡要分析

    這篇文章主要介紹Java網(wǎng)絡(luò)編程中的IO模型阻塞與非阻塞簡要分析,文中附有示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • MyBatis動態(tài)SQL與緩存原理深入分析

    MyBatis動態(tài)SQL與緩存原理深入分析

    這篇文章主要介紹了MyBatis動態(tài)SQL與緩存原理,Mybatis框架的動態(tài)SQL技術(shù)是一種根據(jù)特定條件動態(tài)拼裝SQL語句的功能,它存在的意義是為了解決拼接SQL語句字符串時的痛點問題
    2023-02-02
  • Spring boot學習教程之快速入門篇

    Spring boot學習教程之快速入門篇

    這篇文章主要給大家介紹了關(guān)于Spring boot的相關(guān)資料,本文屬于基礎(chǔ)入門教程,對各位學習Spring boot的新手們具有一定的參考學習價值,,要的朋友們下面來一起看看吧。
    2017-04-04
  • java?啟動參數(shù)?springboot?idea詳解

    java?啟動參數(shù)?springboot?idea詳解

    這篇文章主要介紹了java?啟動參數(shù)?springboot?idea的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09

最新評論