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

Java?開發(fā)中?for和Stream用法對比分析

 更新時間:2026年03月10日 10:23:57   作者:程序員大華  
本文介紹了for循環(huán)和Stream在Java編程中的使用場景和區(qū)別,for循環(huán)適用于簡單的遍歷、中途退出、操作索引等場景,而Stream適用于多步驟數(shù)據(jù)處理、復雜邏輯、并行計算等場景,下面通過例子給大家詳細講解,感興趣的朋友一起看看吧

前幾天寫代碼的時候,有一個很簡單的需求:從一堆用戶里找出 VIP 用戶,把他們的名字轉成大寫,然后再打印出來。

我下意識寫了行 for 循環(huán),但寫到一半又猶豫了,現(xiàn)在不是都推薦用 Stream 嗎?會不會顯得代碼太老派?

于是我在想到底什么時候該用 for,什么時候該用 Stream?

查了一圈資料,發(fā)現(xiàn)很多人和我一樣糾結。其實答案并不復雜,今天給大家分享一下。

一、先看個例子

假設我們有一個字符串列表:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Anna");

現(xiàn)在我們要找出所有以"A"開頭的名字,轉成大寫,然后打印出來。

用傳統(tǒng)的for循環(huán)這樣寫

for (String name : names) {
    if (name.startsWith("A")) {
        System.out.println(name.toUpperCase());
    }
}

邏輯清晰,一步一步來,很好理解。

用Stream怎么寫?

names.stream()
     .filter(name -> name.startsWith("A"))
     .map(String::toUpperCase)
     .forEach(System.out::println);

看起來像一條流水線:先過濾,再轉換,最后打印。

二、它們到底有什么區(qū)別?

簡單說:

  • for 循環(huán)是命令式編程:你告訴計算機每一步怎么做。
  • Stream 是聲明式編程:你只告訴計算機你想做什么,不用管細節(jié)。
對比項for循環(huán)Stream
編程風格一步一步執(zhí)行我要過濾、轉換、收集
代碼長度簡單操作更短復雜操作更短
可讀性簡單邏輯易懂復雜邏輯更清晰
能不能提前退出?能(用 break不能直接 break(但有替代方案)
能不能輕松并行?需自己寫多線程換成 .parallelStream() 就行
性能(小數(shù)據(jù))更快一點點稍慢(有函數(shù)調用開銷)
性能(大數(shù)據(jù) + 并行)手動實現(xiàn)復雜可能快很多

三、什么時候該用 for 循環(huán)?

這 8 種情況,優(yōu)先選 for!

1. 簡單的遍歷打印

for (String item : list) {
    System.out.println(item); 
}

2. 需要中途退出

for (File file : files) {
    if (file.length() == 0) {
        isEmpty = true;
        break; // 發(fā)現(xiàn)空文件就立即停止
    }
}

發(fā)現(xiàn)空文件就立即停止

3. 復雜的條件邏輯

for (Order order : orders) {
    // 復雜的業(yè)務判斷
    if (order.isValid() 
        && (order.isVip() || order.getAmount() > 1000)
        && !order.isCancelled()) {
        processOrder(order);
    }
}

4. 需要維護多個狀態(tài)

int successCount = 0;
int failCount = 0;
List<Result> results = new ArrayList<>();
for (Task task : tasks) {
    try {
        Result result = executeTask(task);
        results.add(result);
        successCount++;
    } catch (Exception e) {
        failCount++;
        logger.error("任務執(zhí)行失敗", e);
    }
}

5. 需要操作索引

for (int i = 0; i < list.size(); i++) {
    if (i % 2 == 0) { // 每隔一個元素處理
        process(list.get(i));
    }
}

6. 循環(huán)體內有復雜邏輯

for (User user : users) {
    // 多個步驟,相互依賴
    Profile profile = buildProfile(user);
    validateProfile(profile);
    saveToDatabase(profile);
    sendNotification(user);
}

7. 性能極其敏感的場合

// 在游戲開發(fā)、算法競賽等場景
for (int i = 0; i < MAX_ITERATIONS; i++) {
    // 極其簡單的數(shù)學運算
    result += array[i] * factor;
}

8. 需要修改原集合

for (int i = 0; i < list.size(); i++) {
    if (shouldRemove(list.get(i))) {
        list.remove(i); // 直接修改原集合
        i--; // 調整索引
    }
}

四、什么時候該用 Stream?

當你遇到這些場景,Stream 就是你的救星!

1. 多步驟數(shù)據(jù)處理

List<Product> results = products.stream()
    .filter(p -> p.getStock() > 0)      // 過濾有庫存的
    .filter(p -> p.getPrice() < 100)    // 過濾價格小于100的
    .sorted(Comparator.comparing(Product::getPrice)) // 按價格排序
    .limit(10)                          // 只取前10個
    .collect(Collectors.toList());      // 收集結果

2. 數(shù)據(jù)轉換和提取

// 從員工列表中提取姓名
List<String> names = employees.stream()
    .map(Employee::getName)  // 提取姓名
    .collect(Collectors.toList());

3. 數(shù)據(jù)統(tǒng)計和分析

// 復雜的統(tǒng)計一句搞定
DoubleSummaryStatistics stats = employees.stream()
    .mapToDouble(Employee::getSalary)
    .summaryStatistics();
System.out.println("平均工資: " + stats.getAverage());
System.out.println("最高工資: " + stats.getMax());
System.out.println("最低工資: " + stats.getMin());

4. 分組和分類

// 按部門分組
Map<Department, List<Employee>> byDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment));
// 按條件分區(qū)
Map<Boolean, List<Employee>> partitioned = employees.stream()
    .collect(Collectors.partitioningBy(emp -> emp.getSalary() > 10000));

5. 去重和排序

List<String> uniqueNames = employees.stream()
    .map(Employee::getName)
    .distinct()             // 去重
    .sorted()               // 排序
    .collect(Collectors.toList());

6. 數(shù)據(jù)查找和匹配

// 是否存在滿足條件的元素
boolean hasManager = employees.stream()
    .anyMatch(emp -> "經理".equals(emp.getPosition()));
// 查找第一個滿足條件的
Optional<Employee> firstRich = employees.stream()
    .filter(emp -> emp.getSalary() > 50000)
    .findFirst();

7. 數(shù)據(jù)拼接和匯總

// 將姓名用逗號拼接
String nameStr = employees.stream()
    .map(Employee::getName)
    .collect(Collectors.joining(", "));
// 數(shù)字求和
double totalSalary = employees.stream()
    .mapToDouble(Employee::getSalary)
    .sum();

8、想輕松開啟并行計算

處理百萬級數(shù)據(jù)?試試這個:

List<String> results = bigList.parallelStream()
    .map(this::expensiveOperation) // 耗時操作
    .collect(Collectors.toList());

只需把 .stream() 換成 .parallelStream(),Java 自動幫你用多線程處理!

而手動寫多線程 for 循環(huán)?光是線程安全、結果合并就夠你頭疼了。

五、常見誤區(qū)

誤區(qū)1:Stream 一定比 for 慢嗎?

不一定!

  • 小數(shù)據(jù)量(比如幾十、幾百個元素):for 確實略快。
  • 大數(shù)據(jù)量 + 并行:parallelStream() 可能快幾倍。
  • 但大多數(shù)業(yè)務代碼,性能差異可以忽略??勺x性更重要!

誤區(qū)2:Stream 不能提前退出?

嚴格來說,Stream 沒有 break,但有些操作會自動短路:

  • findFirst():找到第一個就停
  • anyMatch():匹配到一個就停
  • allMatch() / noneMatch():遇到反例就停

所以,不是不能提前停,只是方式不同。

誤區(qū)3:在 Stream 里隨便改外部變量?

// 錯誤示范!
int count = 0;
list.stream().forEach(item -> {
    if (item.isValid()) {
        count++; // 編譯報錯!count 必須是 final 或 effectively final
    }
});

Stream 設計上鼓勵無副作用——即不要修改外部狀態(tài)。
如果真要計數(shù),應該用 filter().count()

long count = list.stream().filter(Item::isValid).count();

這樣更安全,也更適合并行。

六、使用建議

你的需求推薦寫法
打印、簡單遍歷for-each
需要索引(第幾個)傳統(tǒng) for (int i=0; ...)
找到某個值就退出for + break
過濾 + 轉換 + 排序Stream
分組、統(tǒng)計、求平均值Stream
大數(shù)據(jù)并行處理parallelStream()
邏輯簡單,團隊新人多for(更易懂)
代碼要簡潔、可維護Stream(復雜邏輯時)

七、總結

兩者不是對立關系,而是互補工具。高手會根據(jù)場景靈活切換,寫出既高效又優(yōu)雅的代碼!

for 循環(huán)和 Stream 不是替代關系,而是兩種不同用途的工具。

  • for:比如遍歷打印、中途退出、操作索引、維護多個狀態(tài)、或者邏輯復雜到需要一步步控制,這時候 for 更直接、更靈活、也更容易調試。
  • Stream:比如過濾、轉換、分組、統(tǒng)計、去重、排序……這些操作用 Stream 寫出來就像一條清晰的流水線,代碼簡潔、意圖明確,還天然支持并行。

好的代碼,是用最合適的工具,解決手頭的問題。

相關文章

  • 淺談關于Java中TimeZone鎖競爭引發(fā)的問題解決

    淺談關于Java中TimeZone鎖競爭引發(fā)的問題解決

    本文主要介紹了淺談關于Java中TimeZone鎖競爭引發(fā)的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-02-02
  • springboot集成junit編寫單元測試實戰(zhàn)

    springboot集成junit編寫單元測試實戰(zhàn)

    在做單元測試時,代碼覆蓋率常常被拿來作為衡量測試好壞的指標,本文主要介紹了springboot集成junit編寫單元測試實戰(zhàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Maven配置文件pom.xml詳解

    Maven配置文件pom.xml詳解

    什么是POM?這篇文章主要介紹了Maven的配置文件pom.xml,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 一段代碼搞懂關于Java中List、Set集合及Map的使用

    一段代碼搞懂關于Java中List、Set集合及Map的使用

    這篇文章主要介紹了關于Java中List、Set集合及Map的使用及l(fā)ist,set和map三者的區(qū)別介紹,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-08-08
  • Java實現(xiàn)單機版五子棋游戲的示例代碼

    Java實現(xiàn)單機版五子棋游戲的示例代碼

    五子棋是世界智力運動會競技項目之一,是一種兩人對弈的純策略型棋類游戲,是世界智力運動會競技項目之一。本文將用java語言實現(xiàn)單機版五子棋游戲,感興趣的可以了解一下
    2022-09-09
  • 關于BufferedReader讀取文件指定字符集問題

    關于BufferedReader讀取文件指定字符集問題

    這篇文章主要介紹了關于BufferedReader讀取文件指定字符集問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Trace?在多線程異步體系下傳遞流程解析

    Trace?在多線程異步體系下傳遞流程解析

    這篇文章主要為大家介紹了Trace?在多線程異步體系下傳遞流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • java環(huán)境變量path和classpath的配置

    java環(huán)境變量path和classpath的配置

    這篇文章主要為大家詳細介紹了java系統(tǒng)環(huán)境變量path和classpath的配置過程,感興趣的小伙伴們可以參考一下
    2016-07-07
  • mybatis動態(tài)sql之Map參數(shù)的講解

    mybatis動態(tài)sql之Map參數(shù)的講解

    今天小編就為大家分享一篇關于mybatis動態(tài)sql之Map參數(shù)的講解,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • java文件的簡單讀寫操作方法實例分析

    java文件的簡單讀寫操作方法實例分析

    這篇文章主要介紹了java文件的簡單讀寫操作方法,結合實例形式分析了java文件流進行讀寫操作的方法與相關操作注意事項,需要的朋友可以參考下
    2020-05-05

最新評論

泽普县| 津市市| 清流县| 永康市| 启东市| 渭南市| 乐平市| 台湾省| 兰西县| 凤庆县| 宁安市| 新安县| 博罗县| 德昌县| 精河县| 迁安市| 伊金霍洛旗| 盘锦市| 偃师市| 株洲市| 新蔡县| 苍梧县| 江永县| 英山县| 苍山县| 象山县| 西平县| 大同县| 城固县| 三台县| 奉新县| 朔州市| 静宁县| 来凤县| 库车县| 沂南县| 吉木萨尔县| 安庆市| 巧家县| 姜堰市| 靖边县|