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

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

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

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

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

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

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

一、先看個(gè)例子

假設(shè)我們有一個(gè)字符串列表:

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

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

用傳統(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);

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

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

簡單說:

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

三、什么時(shí)候該用 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. 復(fù)雜的條件邏輯

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

4. 需要維護(hù)多個(gè)狀態(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("任務(wù)執(zhí)行失敗", e);
    }
}

5. 需要操作索引

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

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

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

7. 性能極其敏感的場合

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

8. 需要修改原集合

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

四、什么時(shí)候該用 Stream?

當(dāng)你遇到這些場景,Stream 就是你的救星!

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

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

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

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

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

// 復(fù)雜的統(tǒng)計(jì)一句搞定
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 -> "經(jīng)理".equals(emp.getPosition()));
// 查找第一個(gè)滿足條件的
Optional<Employee> firstRich = employees.stream()
    .filter(emp -> emp.getSalary() > 50000)
    .findFirst();

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

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

8、想輕松開啟并行計(jì)算

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

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

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

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

五、常見誤區(qū)

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

不一定!

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

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

嚴(yán)格來說,Stream 沒有 break,但有些操作會(huì)自動(dòng)短路:

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

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

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

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

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

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

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

六、使用建議

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

七、總結(jié)

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

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

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

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

相關(guān)文章

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

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

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

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

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

    Maven配置文件pom.xml詳解

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

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

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

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

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

    關(guān)于BufferedReader讀取文件指定字符集問題

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

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

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

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

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

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

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

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

    這篇文章主要介紹了java文件的簡單讀寫操作方法,結(jié)合實(shí)例形式分析了java文件流進(jìn)行讀寫操作的方法與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2020-05-05

最新評論

晋州市| 乐安县| 林甸县| 临西县| 瑞昌市| 淮阳县| 望谟县| 长兴县| 南昌县| 广丰县| 溆浦县| 红安县| 临沂市| 营口市| 阿城市| 定兴县| 黄龙县| 慈利县| 宁海县| 措勤县| 平顶山市| 岳阳县| 霸州市| 陆良县| 永吉县| 绵阳市| 和林格尔县| 弥勒县| 清水河县| 西畴县| 固安县| 汝南县| 南投市| 攀枝花市| 盱眙县| 遂平县| 重庆市| 盘锦市| 嫩江县| 沛县| 淮安市|