最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的Stream流式操作大全

 更新時間:2025年12月18日 11:54:50   作者:heartbeat..  
Java 8引入的Stream API提供了一種高效、簡潔的集合數(shù)據(jù)處理方式,基于函數(shù)式編程思想,支持惰性求值、一次性消費(fèi)、無狀態(tài)/有狀態(tài)操作和并行處理,本文通過實(shí)例代碼介紹java中的Stream流式操作,感興趣的朋友跟隨小編一起看看吧

一、介紹

  在 Java 8 及以上版本中,Stream(流式操作) 是處理集合(Collection)、數(shù)組等數(shù)據(jù)的高效工具,它基于函數(shù)式編程思想,提供了聲明式(而非命令式)的數(shù)據(jù)處理方式,核心優(yōu)勢是 簡潔、高效、可并行。
   Stream 本質(zhì)是數(shù)據(jù)的 “流水線”數(shù)據(jù)從數(shù)據(jù)源(集合、數(shù)組等)流入,經(jīng)過一系列中間操作(過濾、映射、排序等)的 “加工”,最終通過終端操作(統(tǒng)計(jì)、收集、遍歷等)輸出結(jié)果(或無輸出)。
   這個 “流水線” 可以用 “工廠食品加工生產(chǎn)線” 來形象比喻,每個環(huán)節(jié)和 Stream 操作一一對應(yīng),特別好理解:

你可以把 Stream 想象成一條 自動化食品加工生產(chǎn)線

  • 「數(shù)據(jù)源」= 生產(chǎn)線的 “原料倉庫”:比如一堆新鮮的蔬菜(對應(yīng)集合 / 數(shù)組里的原始數(shù)據(jù)),是加工的起點(diǎn);
  • 「中間操作」= 生產(chǎn)線的 “加工工序”:比如 “篩選(去掉腐爛的蔬菜)”“切割(切成小塊)”“清洗(去掉泥沙)”“調(diào)味(加調(diào)料)”,每個工序只負(fù)責(zé)自己的加工,不直接產(chǎn)出最終產(chǎn)品(惰性求值),而是把加工后的原料傳到下一道工序;
  • 「終端操作」= 生產(chǎn)線的 “成品包裝 / 出庫”:比如 “裝盒打包”“稱重計(jì)數(shù)”“直接運(yùn)往超市”,只有啟動這一步,前面所有加工工序才會真正運(yùn)轉(zhuǎn)(觸發(fā)計(jì)算),最終產(chǎn)出成品(對應(yīng) Stream 的結(jié)果)或完成交付(比如 forEach 遍歷相當(dāng)于 “把食品分發(fā)給消費(fèi)者”,無返回值)。

補(bǔ)充兩個貼合 Stream 特性的細(xì)節(jié):

  1. 原料只能用一次:同一批蔬菜(同一個 Stream)經(jīng)過生產(chǎn)線(終端操作)后,就變成了成品,不能再放回倉庫重新加工(Stream 一次性消費(fèi));
  2. 可選 “并行加工”:普通生產(chǎn)線是單條流水線(串行流),如果原料太多,可啟動多條并行流水線(并行流),同時處理不同批次的原料,最后合并成品,效率更高。

二、特性

  1. 惰性求值:中間操作不會立即執(zhí)行,只有調(diào)用終端操作時,才會觸發(fā)整個流水線的計(jì)算(節(jié)省資源)。
  2. 一次性消費(fèi):一個 Stream 只能被使用一次,執(zhí)行終端操作后會自動關(guān)閉,再次使用會拋出異常。
  3. 無狀態(tài) / 有狀態(tài)操作
    • 無狀態(tài):每個元素的處理獨(dú)立(如 filter(篩選)、map(映射)),不依賴其他元素;
    • 有狀態(tài):處理元素需要依賴其他元素(如 sorted(自然排序)distinct(去重)、limit(限制)),可能需要緩存數(shù)據(jù)。
  4. 并行支持:通過 parallelStream() 或 stream.parallel() 輕松實(shí)現(xiàn)并行處理(底層依賴 Fork/Join 框架)。

三、操作

完整的 Stream 操作分為 3 步:

  1. 創(chuàng)建 Stream:從數(shù)據(jù)源(集合、數(shù)組、生成器等)獲取 Stream;
  2. 中間操作:對數(shù)據(jù)進(jìn)行過濾、映射、排序等加工(可多個中間操作鏈?zhǔn)秸{(diào)用);
  3. 終端操作:觸發(fā)計(jì)算,輸出結(jié)果(或執(zhí)行副作用,如遍歷),Stream 生命周期結(jié)束。

流程圖

集合/數(shù)組 → 創(chuàng)建 Stream → 中間操作1 → 中間操作2 → ... → 終端操作 → 結(jié)果

四、詳解

1. 創(chuàng)建 Stream(數(shù)據(jù)源)

(1)從集合創(chuàng)建(最常用)

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream(); // 串行流
Stream<String> parallelStream = list.parallelStream(); // 并行流

(2)從數(shù)組創(chuàng)建

String[] arr = {"x", "y", "z"};
Stream<String> stream = Arrays.stream(arr);
// 部分?jǐn)?shù)組(從索引1到2,左閉右開)
Stream<String> partStream = Arrays.stream(arr, 1, 3);

(3)通過 Stream.of () 創(chuàng)建

Stream<Integer> stream = Stream.of(1, 2, 3, 4);
Stream<Object> emptyStream = Stream.empty(); // 空流

(4)無限流(生成器 / 迭代器)

  適用于需要動態(tài)生成數(shù)據(jù)的場景(需配合 limit 限制長度,否則無限循環(huán)):

// 1. generate:生成固定值或隨機(jī)值(Supplier接口)
Stream<Double> randomStream = Stream.generate(Math::random).limit(5); // 5個隨機(jī)數(shù)
// 2. iterate:迭代生成(種子 -> 下一個元素,UnaryOperator接口)
Stream<Integer> numStream = Stream.iterate(0, n -> n + 2).limit(5); // 0,2,4,6,8

2. 中間操作(加工數(shù)據(jù))

中間操作返回新的 Stream,支持鏈?zhǔn)秸{(diào)用,常用操作如下:

操作功能描述示例(以 List<Integer> list = [1,2,3,4,5,6] 為例)
filter(Predicate)過濾元素(滿足條件保留)list.stream().filter(n -> n % 2 == 0) → [2,4,6]
map(Function)元素映射(轉(zhuǎn)換為另一種類型)list.stream().map(n -> n * 2) → [2,4,6,8,10,12]
flatMap(Function)扁平化映射(將流中的流展開為單個流)List<List<Integer>> list2 = [[1,2],[3,4]]; list2.stream().flatMap(Collection::stream) → [1,2,3,4]
distinct()去重(基于 equals() 方法)Stream.of(1,2,2,3).distinct() → [1,2,3]
sorted()自然排序(元素需實(shí)現(xiàn) ComparableStream.of(3,1,2).sorted() → [1,2,3]
sorted(Comparator)自定義排序list.stream().sorted((a,b) -> b - a) → [6,5,4,3,2,1]
limit(long)限制返回前 N 個元素list.stream().limit(3) → [1,2,3]
skip(long)跳過前 N 個元素list.stream().skip(3) → [4,5,6]
peek(Consumer)遍歷元素(無修改,常用于調(diào)試)list.stream().peek(System.out::println).count() → 打印所有元素后返回計(jì)數(shù)

3. 終端操作(觸發(fā)計(jì)算)

終端操作會消耗 Stream,返回非 Stream 結(jié)果(或無返回),常用操作如下:

(1)遍歷與消費(fèi)

  • forEach(Consumer):遍歷元素(最常用,有副作用);
  • forEachOrdered(Consumer):并行流中保證遍歷順序(串行流與 forEach 無區(qū)別)。
    List<String> list = Arrays.asList("a", "b", "c");
    list.stream().forEach(System.out::println); // 輸出 a b c(并行流可能亂序)
    list.parallelStream().forEachOrdered(System.out::println); // 保證順序 a b c

(2)聚合統(tǒng)計(jì)(返回單個值)

操作功能描述示例
count()返回元素個數(shù)(long 類型)Stream.of(1,2,3).count() → 3
max(Comparator)返回最大值(Optional 類型,避免空指針)Stream.of(1,2,3).max(Integer::compare) → Optional[3]
min(Comparator)返回最小值Stream.of(1,2,3).min(Integer::compare) → Optional[1]
findFirst()返回第一個元素(Optional,串行流高效)Stream.of(1,2,3).findFirst() → Optional[1]
findAny()返回任意一個元素(并行流高效)Stream.of(1,2,3).parallel().findAny() → 可能是 1/2/3
anyMatch(Predicate)是否存在滿足條件的元素(短路求值)Stream.of(1,2,3).anyMatch(n -> n > 2) → true
allMatch(Predicate)所有元素是否滿足條件(短路求值)Stream.of(1,2,3).allMatch(n -> n > 0) → true
noneMatch(Predicate)所有元素是否都不滿足條件(短路求值)Stream.of(1,2,3).noneMatch(n -> n < 0) → true

   短路求值:一旦滿足條件就停止計(jì)算(如 anyMatch 找到一個滿足條件的元素就返回,無需遍歷所有)。

    (3)收集結(jié)果(collect(Collector))

      將 Stream 結(jié)果收集為集合、數(shù)組、Map 等,由Collectors 工具類提供了大量預(yù)定義收集器。

      ① 收集為集合

    List<Integer> list = Stream.of(1,2,3).collect(Collectors.toList()); // 默認(rèn) ArrayList
    List<Integer> linkedList = Stream.of(1,2,3).collect(Collectors.toCollection(LinkedList::new)); // 指定集合
    Set<Integer> set = Stream.of(1,2,2).collect(Collectors.toSet()); // 去重集合

      ② 收集為數(shù)組

    Integer[] arr = Stream.of(1,2,3).toArray(Integer[]::new); // 推薦(類型安全)
    Object[] objArr = Stream.of(1,2,3).toArray(); // 不推薦(需要強(qiáng)轉(zhuǎn))

      ③ 收集為 Map(注意 key 唯一)

    List<String> userList = Arrays.asList("id1:張三", "id2:李四", "id3:王五");
    // key: 拆分后的id,value: 拆分后的姓名
    Map<String, String> userMap = userList.stream()
        .map(user -> user.split(":")) // 拆分后為 String[]
        .collect(Collectors.toMap(
            arr -> arr[0], // key 映射
            arr -> arr[1]  // value 映射
        ));
    // 若 key 可能重復(fù),需指定沖突解決策略(如保留第一個)
    Map<String, String> userMapSafe = userList.stream()
        .map(user -> user.split(":"))
        .collect(Collectors.toMap(
            arr -> arr[0],
            arr -> arr[1],
            (v1, v2) -> v1 // 沖突時保留第一個值
        ));

      ④ 聚合統(tǒng)計(jì)(求和、平均值等)

    List<Integer> numList = Arrays.asList(1,2,3,4,5);
    // 求和(Integer 類型)
    int sum = numList.stream().collect(Collectors.summingInt(Integer::intValue));
    // 求和(Long 類型,避免溢出)
    long sumLong = numList.stream().collect(Collectors.summingLong(Integer::longValue));
    // 平均值(返回 Double)
    double avg = numList.stream().collect(Collectors.averagingInt(Integer::intValue));
    // 統(tǒng)計(jì)信息(總和、平均值、計(jì)數(shù)等)
    IntSummaryStatistics stats = numList.stream().collect(Collectors.summarizingInt(Integer::intValue));
    System.out.println("總和:" + stats.getSum());
    System.out.println("平均值:" + stats.getAverage());
    System.out.println("最大值:" + stats.getMax());
      ⑤ 分組(groupingBy

      按指定條件分組,返回 Map<分組鍵, List<元素>>

    List<String> fruitList = Arrays.asList("蘋果", "香蕉", "橙子", "紅蘋果", "青蘋果");
    // 按首字符分組
    Map<Character, List<String>> groupByFirstChar = fruitList.stream()
        .collect(Collectors.groupingBy(fruit -> fruit.charAt(0)));
    // 結(jié)果:{蘋=[蘋果, 紅蘋果, 青蘋果], 香=[香蕉], 橙=[橙子]}
    // 分組后統(tǒng)計(jì)個數(shù)(返回 Map<分組鍵, 計(jì)數(shù)>)
    Map<Character, Long> countByGroup = fruitList.stream()
        .collect(Collectors.groupingBy(
            fruit -> fruit.charAt(0),
            Collectors.counting() // 下游收集器:統(tǒng)計(jì)個數(shù)
        ));
    // 結(jié)果:{蘋=3, 香=1, 橙=1}

      ⑥ 拼接字符串(joining

    List<String> strList = Arrays.asList("a", "b", "c");
    String join1 = strList.stream().collect(Collectors.joining()); // "abc"
    String join2 = strList.stream().collect(Collectors.joining(",")); // "a,b,c"
    String join3 = strList.stream().collect(Collectors.joining(",", "[", "]")); // "[a,b,c]"

    五、并行

    Stream 天生支持并行,只需將串行流轉(zhuǎn)為并行流,無需手動處理線程:

    1. 集合直接獲取并行流:list.parallelStream();
    2. 串行流轉(zhuǎn)為并行流:stream.parallel()

    注意:

    • 線程安全:若中間操作修改外部變量(如全局集合),需保證線程安全(建議使用無狀態(tài)操作,避免副作用);
    • 順序性:并行流的 forEach 可能亂序,需順序則用 forEachOrdered(但會降低并行效率);
    • 性能考量:數(shù)據(jù)量小時,并行流的線程開銷可能超過收益(建議數(shù)據(jù)量 > 1000 時使用)
    • 處理效率:數(shù)據(jù)量越大,并行流優(yōu)勢越明顯(小數(shù)據(jù)量可能因線程開銷導(dǎo)致效率更低)。
    • 非線程安全的數(shù)據(jù)源:如 ArrayList 是線程安全的(讀取時),但 LinkedList 并行效率低,建議使用數(shù)組或 ArrayList 作為并行流數(shù)據(jù)源。

    示例:

    List<Integer> numList = IntStream.range(1, 1000000).boxed().collect(Collectors.toList());
    // 串行流求和(耗時較長)
    long serialSum = numList.stream().mapToLong(Integer::longValue).sum();
    // 并行流求和(效率更高)
    long parallelSum = numList.parallelStream().mapToLong(Integer::longValue).sum();

    六、注意

    1. 忘記終端操作:只寫中間操作不寫終端操作,代碼不會執(zhí)行;
    2. 重復(fù)使用 Stream:一個 Stream 執(zhí)行終端操作后關(guān)閉,再次使用會拋出 IllegalStateException;
    3. 并行流的副作用:并行流中修改外部非線程安全的變量(如 ArrayList),會導(dǎo)致數(shù)據(jù)錯亂;
    4. 濫用 peekpeek 設(shè)計(jì)用于調(diào)試,不建議用于修改元素(雖然語法允許);
    5. 忽略 Optional 空指針風(fēng)險(xiǎn):maxfindFirst 等返回 Optional,直接調(diào)用 get() 可能拋出 NoSuchElementException,建議用 orElse() 或 ifPresent() 處理空值:
    // 錯誤:無元素時拋出異常
    Integer max = Stream.empty().max(Integer::compare).get();
    // 正確:無元素時返回默認(rèn)值 0
    Integer maxSafe = Stream.empty().max(Integer::compare).orElse(0);

    七、總結(jié)

      Stream 是 Java 處理集合數(shù)據(jù)的利器,特點(diǎn)總結(jié):

    • 簡潔:用鏈?zhǔn)秸{(diào)用替代嵌套循環(huán),代碼可讀性高;
    • 高效:惰性求值 + 并行支持,處理大數(shù)據(jù)更高效;
    • 靈活:豐富的中間操作和終端操作,覆蓋大部分?jǐn)?shù)據(jù)處理場景。

      實(shí)際開發(fā)中,建議用 Stream 替代傳統(tǒng)的 for 循環(huán)和 Iterator,尤其是處理復(fù)雜數(shù)據(jù)轉(zhuǎn)換、過濾、統(tǒng)計(jì)時,能大幅提升開發(fā)效率和代碼質(zhì)量。

    到此這篇關(guān)于Java中的Stream流式操作大全的文章就介紹到這了,更多相關(guān)java stream流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

    相關(guān)文章

    • Spring?IoC容器Bean作用域的singleton與prototype使用配置

      Spring?IoC容器Bean作用域的singleton與prototype使用配置

      這篇文章主要為大家介紹了Spring?IoC容器Bean作用域的singleton與prototype使用配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
      2023-12-12
    • SpringBoot返回所有接口詳細(xì)信息的方法詳解

      SpringBoot返回所有接口詳細(xì)信息的方法詳解

      這篇文章主要介紹了SpringBoot返回所有接口詳細(xì)信息的方法,簡單來說就是我們通過訪問一個接口能看到我們所有的API接口的數(shù)量,以及路徑和請求方法,文中有詳細(xì)的代碼供大家參考,需要的朋友可以參考下
      2025-04-04
    • Spring Boot 分布式鎖與并發(fā)控制的應(yīng)用場景

      Spring Boot 分布式鎖與并發(fā)控制的應(yīng)用場景

      本章主要介紹了SpringBoot分布式鎖與并發(fā)控制的核心概念與使用方法,包括分布式鎖的定義與特點(diǎn)、并發(fā)控制的定義與特點(diǎn)、SpringBoot與分布式鎖的集成、SpringBoot的實(shí)際應(yīng)用場景,感興趣的朋友跟隨小編一起看看吧
      2026-03-03
    • Java工具類實(shí)現(xiàn)高效編寫報(bào)表

      Java工具類實(shí)現(xiàn)高效編寫報(bào)表

      對于報(bào)表數(shù)據(jù)大部分情況下使用寫sql的方式為大屏/報(bào)表提供數(shù)據(jù)來源,但是對于某些復(fù)雜情況下僅僅使用sql無法實(shí)現(xiàn),這篇文章主要介紹了Java工具類實(shí)現(xiàn)高效編寫報(bào)表
      2022-11-11
    • 基于Spring p標(biāo)簽和c標(biāo)簽注入方式

      基于Spring p標(biāo)簽和c標(biāo)簽注入方式

      這篇文章主要介紹了Spring p標(biāo)簽和c標(biāo)簽注入方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
      2021-09-09
    • 基于SpringBoot + MyBatis-Plus高效實(shí)現(xiàn)數(shù)據(jù)變更記錄

      基于SpringBoot + MyBatis-Plus高效實(shí)現(xiàn)數(shù)據(jù)變更記錄

      在應(yīng)用開發(fā)過程中,在某些情況下,需要實(shí)現(xiàn)數(shù)據(jù)的變更記錄,以便于在未來進(jìn)行數(shù)據(jù)操作變更的回溯,那有什么辦法高效實(shí)現(xiàn)數(shù)據(jù)操作變更記錄,而不需要一個一個地方去加呢?答案當(dāng)然是有,今天小編就給大家介紹下如何基于SpringBoot + MyBatis-Plus高效實(shí)現(xiàn)數(shù)據(jù)的變更記錄,
      2026-02-02
    • 解析ConcurrentHashMap: 紅黑樹的代理類(TreeBin)

      解析ConcurrentHashMap: 紅黑樹的代理類(TreeBin)

      ConcurrentHashMap是由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成。Segment的結(jié)構(gòu)和HashMap類似,是一種數(shù)組和鏈表結(jié)構(gòu),今天給大家普及java面試常見問題---ConcurrentHashMap知識,一起看看吧
      2021-06-06
    • 簡單談?wù)凧ava垃圾回收

      簡單談?wù)凧ava垃圾回收

      本文是看了James Gosling的<<Java程序設(shè)計(jì)語言>>后結(jié)合自己的一些項(xiàng)目經(jīng)驗(yàn),簡單總結(jié)下關(guān)于java的垃圾回收問題的看法,有需要的小伙伴可以參考下
      2016-05-05
    • Java基礎(chǔ)之垃圾回收機(jī)制詳解

      Java基礎(chǔ)之垃圾回收機(jī)制詳解

      這篇文章主要介紹了Java基礎(chǔ)之垃圾回收機(jī)制詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
      2021-04-04
    • Mybatis自定義TypeHandler解決特殊類型轉(zhuǎn)換問題詳解

      Mybatis自定義TypeHandler解決特殊類型轉(zhuǎn)換問題詳解

      這篇文章主要介紹了Mybatis自定義TypeHandler解決特殊類型轉(zhuǎn)換問題詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
      2019-11-11

    最新評論

    华安县| 保亭| 宁化县| 惠安县| 满城县| 肃南| 吉水县| 固原市| 织金县| 边坝县| 慈溪市| 蒙山县| 仲巴县| 淮安市| 旌德县| 江门市| 都兰县| 和林格尔县| 台北市| 朝阳县| 洞头县| 明水县| 滦平县| 南投县| 岑巩县| 莱芜市| 道真| 南华县| 宁化县| 南丹县| 光泽县| 宁陕县| 长汀县| 阿拉尔市| 昌图县| 汝南县| 托克逊县| 尉氏县| 夏河县| 夹江县| 西城区|