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

Java Stream流從入門到精通

 更新時(shí)間:2025年11月11日 15:08:17   作者:待畔逢  
Stream(流)是Java 8引入的一個(gè)重要特性,它提供了一種聲明式的數(shù)據(jù)處理方式,本文給大家介紹Java Stream流從入門到精通,感興趣的朋友跟隨小編一起看看吧

Java Stream流詳解:從入門到精通

1. Stream流簡(jiǎn)介

什么是Stream?

Stream(流)是Java 8引入的一個(gè)重要特性,它提供了一種聲明式的數(shù)據(jù)處理方式。Stream不是數(shù)據(jù)結(jié)構(gòu),而是對(duì)數(shù)據(jù)源(如集合、數(shù)組等)進(jìn)行操作的抽象。

為什么要使用Stream?

傳統(tǒng)的集合操作往往需要編寫大量的循環(huán)代碼,而Stream提供了更加簡(jiǎn)潔、易讀的函數(shù)式編程風(fēng)格:

// 傳統(tǒng)方式:找出年齡大于18的用戶姓名
List<String> result = new ArrayList<>();
for (User user : users) {
    if (user.getAge() > 18) {
        result.add(user.getName());
    }
}
// Stream方式
List<String> result = users.stream()
    .filter(user -> user.getAge() > 18)
    .map(User::getName)
    .collect(Collectors.toList());

2. Stream的特點(diǎn)

2.1 主要特征

  1. 不存儲(chǔ)數(shù)據(jù):Stream不是數(shù)據(jù)結(jié)構(gòu),不會(huì)存儲(chǔ)元素
  2. 函數(shù)式編程:支持鏈?zhǔn)秸{(diào)用,代碼更簡(jiǎn)潔
  3. 惰性求值:中間操作不會(huì)立即執(zhí)行,只有遇到終端操作才會(huì)執(zhí)行
  4. 可消費(fèi)性:Stream只能被消費(fèi)一次

2.2 Stream操作分類

// 中間操作(Intermediate Operations)
// 返回Stream對(duì)象,支持鏈?zhǔn)秸{(diào)用
stream.filter().map().sorted()
// 終端操作(Terminal Operations)  
// 返回具體結(jié)果,觸發(fā)流的執(zhí)行
stream.collect().forEach().reduce()

3. 創(chuàng)建Stream流

3.1 從集合創(chuàng)建

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

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

String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
// 指定范圍
Stream<String> stream2 = Arrays.stream(array, 1, 3);

3.3 直接創(chuàng)建

// 通過(guò)Stream.of()
Stream<String> stream = Stream.of("a", "b", "c");
// 創(chuàng)建空流
Stream<String> empty = Stream.empty();
// 創(chuàng)建無(wú)限流
Stream<Integer> iterate = Stream.iterate(0, n -> n + 2);
Stream<Double> generate = Stream.generate(Math::random);

3.4 從文件創(chuàng)建

try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    lines.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}

4. 中間操作詳解

4.1 filter() - 過(guò)濾

根據(jù)條件過(guò)濾元素:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 過(guò)濾出偶數(shù)
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
// 結(jié)果:[2, 4, 6, 8, 10]

4.2 map() - 映射轉(zhuǎn)換

將元素轉(zhuǎn)換為其他形式:

List<String> words = Arrays.asList("hello", "world", "java");
// 轉(zhuǎn)換為大寫
List<String> upperCase = words.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
// 結(jié)果:["HELLO", "WORLD", "JAVA"]
// 獲取字符串長(zhǎng)度
List<Integer> lengths = words.stream()
    .map(String::length)
    .collect(Collectors.toList());
// 結(jié)果:[5, 5, 4]

4.3 flatMap() - 扁平化映射

將嵌套結(jié)構(gòu)扁平化:

List<List<String>> nested = Arrays.asList(
    Arrays.asList("a", "b"),
    Arrays.asList("c", "d"),
    Arrays.asList("e", "f")
);
// 扁平化處理
List<String> flattened = nested.stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList());
// 結(jié)果:["a", "b", "c", "d", "e", "f"]

4.4 distinct() - 去重

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4, 5);
List<Integer> unique = numbers.stream()
    .distinct()
    .collect(Collectors.toList());
// 結(jié)果:[1, 2, 3, 4, 5]

4.5 sorted() - 排序

List<String> words = Arrays.asList("banana", "apple", "cherry");
// 自然排序
List<String> sorted = words.stream()
    .sorted()
    .collect(Collectors.toList());
// 結(jié)果:["apple", "banana", "cherry"]
// 自定義排序
List<String> sortedByLength = words.stream()
    .sorted(Comparator.comparing(String::length))
    .collect(Collectors.toList());
// 結(jié)果:["apple", "banana", "cherry"]

4.6 limit() 和 skip()

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 限制元素?cái)?shù)量
List<Integer> limited = numbers.stream()
    .limit(5)
    .collect(Collectors.toList());
// 結(jié)果:[1, 2, 3, 4, 5]
// 跳過(guò)前幾個(gè)元素
List<Integer> skipped = numbers.stream()
    .skip(5)
    .collect(Collectors.toList());
// 結(jié)果:[6, 7, 8, 9, 10]
// 分頁(yè)效果:跳過(guò)前5個(gè),取3個(gè)
List<Integer> page = numbers.stream()
    .skip(5)
    .limit(3)
    .collect(Collectors.toList());
// 結(jié)果:[6, 7, 8]

5. 終端操作詳解

5.1 collect() - 收集結(jié)果

List<String> words = Arrays.asList("apple", "banana", "cherry");
// 收集到List
List<String> list = words.stream().collect(Collectors.toList());
// 收集到Set
Set<String> set = words.stream().collect(Collectors.toSet());
// 收集到Map
Map<String, Integer> map = words.stream()
    .collect(Collectors.toMap(
        word -> word,           // key
        String::length          // value
    ));
// 分組
Map<Integer, List<String>> grouped = words.stream()
    .collect(Collectors.groupingBy(String::length));
// 連接字符串
String joined = words.stream()
    .collect(Collectors.joining(", "));
// 結(jié)果:"apple, banana, cherry"

5.2 forEach() - 遍歷

List<String> words = Arrays.asList("apple", "banana", "cherry");
// 打印每個(gè)元素
words.stream().forEach(System.out::println);
// 并行遍歷(注意:順序不保證)
words.parallelStream().forEach(System.out::println);
// 有序遍歷
words.parallelStream().forEachOrdered(System.out::println);

5.3 reduce() - 歸約

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 求和
Optional<Integer> sum = numbers.stream()
    .reduce((a, b) -> a + b);
// 帶初始值的求和
Integer sum2 = numbers.stream()
    .reduce(0, (a, b) -> a + b);
// 求最大值
Optional<Integer> max = numbers.stream()
    .reduce(Integer::max);
// 字符串連接
List<String> words = Arrays.asList("Hello", " ", "World");
String result = words.stream()
    .reduce("", String::concat);
// 結(jié)果:"Hello World"

5.4 查找操作

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 查找任意一個(gè)偶數(shù)
Optional<Integer> any = numbers.stream()
    .filter(n -> n % 2 == 0)
    .findAny();
// 查找第一個(gè)偶數(shù)
Optional<Integer> first = numbers.stream()
    .filter(n -> n % 2 == 0)
    .findFirst();

5.5 匹配操作

List<Integer> numbers = Arrays.asList(2, 4, 6, 8);
// 是否所有元素都是偶數(shù)
boolean allEven = numbers.stream()
    .allMatch(n -> n % 2 == 0);  // true
// 是否存在偶數(shù)
boolean anyEven = numbers.stream()
    .anyMatch(n -> n % 2 == 0);  // true
// 是否沒(méi)有奇數(shù)
boolean noneOdd = numbers.stream()
    .noneMatch(n -> n % 2 == 1); // true

5.6 統(tǒng)計(jì)操作

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 計(jì)數(shù)
long count = numbers.stream().count();
// 數(shù)值流統(tǒng)計(jì)
IntSummaryStatistics stats = numbers.stream()
    .mapToInt(Integer::intValue)
    .summaryStatistics();
System.out.println("Count: " + stats.getCount());
System.out.println("Sum: " + stats.getSum());
System.out.println("Average: " + stats.getAverage());
System.out.println("Max: " + stats.getMax());
System.out.println("Min: " + stats.getMin());

6. 實(shí)際應(yīng)用案例

6.1 用戶數(shù)據(jù)處理

public class User {
    private String name;
    private int age;
    private String city;
    private double salary;
    // 構(gòu)造函數(shù)、getter、setter省略
}
List<User> users = Arrays.asList(
    new User("張三", 25, "北京", 8000),
    new User("李四", 30, "上海", 12000),
    new User("王五", 22, "北京", 6000),
    new User("趙六", 28, "深圳", 15000)
);
// 案例1:找出年齡大于25歲,在北京工作的用戶姓名
List<String> result1 = users.stream()
    .filter(user -> user.getAge() > 25)
    .filter(user -> "北京".equals(user.getCity()))
    .map(User::getName)
    .collect(Collectors.toList());
// 案例2:按城市分組統(tǒng)計(jì)平均工資
Map<String, Double> avgSalaryByCity = users.stream()
    .collect(Collectors.groupingBy(
        User::getCity,
        Collectors.averagingDouble(User::getSalary)
    ));
// 案例3:找出工資最高的用戶
Optional<User> highestPaid = users.stream()
    .max(Comparator.comparing(User::getSalary));
// 案例4:計(jì)算所有用戶的總工資
double totalSalary = users.stream()
    .mapToDouble(User::getSalary)
    .sum();

6.2 文件處理

// 讀取文件并統(tǒng)計(jì)單詞頻率
public Map<String, Long> countWords(String filePath) {
    try (Stream<String> lines = Files.lines(Paths.get(filePath))) {
        return lines
            .flatMap(line -> Arrays.stream(line.split("\\s+")))
            .filter(word -> !word.isEmpty())
            .map(String::toLowerCase)
            .collect(Collectors.groupingBy(
                Function.identity(),
                Collectors.counting()
            ));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

6.3 數(shù)據(jù)轉(zhuǎn)換

// 將CSV數(shù)據(jù)轉(zhuǎn)換為對(duì)象
public List<Product> parseCSV(List<String> csvLines) {
    return csvLines.stream()
        .skip(1) // 跳過(guò)標(biāo)題行
        .map(line -> line.split(","))
        .filter(fields -> fields.length >= 3)
        .map(fields -> new Product(
            fields[0].trim(),
            Double.parseDouble(fields[1].trim()),
            Integer.parseInt(fields[2].trim())
        ))
        .collect(Collectors.toList());
}

7. 性能優(yōu)化建議

7.1 選擇合適的流類型

// 對(duì)于大數(shù)據(jù)集,考慮使用并行流
List<Integer> largeList = IntStream.range(0, 1000000)
    .boxed()
    .collect(Collectors.toList());
// 串行流
long serialTime = System.currentTimeMillis();
long serialSum = largeList.stream()
    .mapToLong(Integer::longValue)
    .sum();
serialTime = System.currentTimeMillis() - serialTime;
// 并行流
long parallelTime = System.currentTimeMillis();
long parallelSum = largeList.parallelStream()
    .mapToLong(Integer::longValue)
    .sum();
parallelTime = System.currentTimeMillis() - parallelTime;

7.2 避免裝箱拆箱

// 不推薦:會(huì)產(chǎn)生裝箱拆箱開(kāi)銷
int sum1 = numbers.stream()
    .mapToInt(Integer::intValue)
    .sum();
// 推薦:直接使用基本類型流
int sum2 = IntStream.of(1, 2, 3, 4, 5).sum();

7.3 合理使用短路操作

// 使用短路操作提高效率
boolean hasEven = numbers.stream()
    .anyMatch(n -> n % 2 == 0); // 找到第一個(gè)偶數(shù)就返回
// 限制處理數(shù)量
List<String> first10 = largeStringList.stream()
    .filter(s -> s.length() > 5)
    .limit(10)
    .collect(Collectors.toList());

8. 常見(jiàn)陷阱與注意事項(xiàng)

8.1 Stream只能使用一次

Stream<String> stream = Stream.of("a", "b", "c");
stream.forEach(System.out::println); // 正常
// stream.count(); // 拋出IllegalStateException

8.2 并行流的線程安全

// 錯(cuò)誤:非線程安全的操作
List<String> result = new ArrayList<>();
words.parallelStream().forEach(result::add); // 可能導(dǎo)致數(shù)據(jù)丟失
// 正確:使用線程安全的收集器
List<String> result = words.parallelStream()
    .collect(Collectors.toList());

8.3 注意null值處理

List<String> words = Arrays.asList("hello", null, "world");
// 過(guò)濾null值
List<String> filtered = words.stream()
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

9. 總結(jié)

Stream流是Java 8引入的強(qiáng)大特性,它提供了:

優(yōu)點(diǎn)

  • 簡(jiǎn)潔性:減少樣板代碼,提高代碼可讀性
  • 函數(shù)式編程:支持鏈?zhǔn)秸{(diào)用,代碼更優(yōu)雅
  • 并行處理:輕松實(shí)現(xiàn)并行計(jì)算
  • 惰性求值:提高性能,按需計(jì)算

適用場(chǎng)景

  • 集合數(shù)據(jù)的過(guò)濾、轉(zhuǎn)換、聚合
  • 大數(shù)據(jù)集的并行處理
  • 復(fù)雜的數(shù)據(jù)查詢和統(tǒng)計(jì)
  • 函數(shù)式編程風(fēng)格的代碼

最佳實(shí)踐

  1. 優(yōu)先使用Stream API替代傳統(tǒng)循環(huán)
  2. 合理選擇串行流和并行流
  3. 注意Stream的一次性使用特性
  4. 使用基本類型流避免裝箱開(kāi)銷
  5. 善用短路操作提高性能

通過(guò)掌握Stream流,你可以寫出更加簡(jiǎn)潔、高效、易維護(hù)的Java代碼。在實(shí)際開(kāi)發(fā)中,Stream已經(jīng)成為處理集合數(shù)據(jù)的標(biāo)準(zhǔn)方式,值得每個(gè)Java開(kāi)發(fā)者深入學(xué)習(xí)和應(yīng)用。

到此這篇關(guān)于Java Stream流從入門到精通的文章就介紹到這了,更多相關(guān)Java Stream流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Calendar類使用案例詳解

    Java Calendar類使用案例詳解

    這篇文章主要介紹了Java Calendar類使用案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • IntelliJ IDEA連接MySQL數(shù)據(jù)庫(kù)詳細(xì)圖解

    IntelliJ IDEA連接MySQL數(shù)據(jù)庫(kù)詳細(xì)圖解

    今天小編就為大家分享一篇關(guān)于intellij idea連接mysql數(shù)據(jù)庫(kù)詳細(xì)圖解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • 如何解決HttpServletRequest.getInputStream()多次讀取問(wèn)題

    如何解決HttpServletRequest.getInputStream()多次讀取問(wèn)題

    這篇文章主要介紹了如何解決HttpServletRequest.getInputStream()多次讀取問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java中2個(gè)對(duì)象字段值比較是否相同

    Java中2個(gè)對(duì)象字段值比較是否相同

    本文主要介紹了Java中2個(gè)對(duì)象字段值比較是否相同,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • java隨機(jī)生成一個(gè)名字和對(duì)應(yīng)拼音的方法

    java隨機(jī)生成一個(gè)名字和對(duì)應(yīng)拼音的方法

    這篇文章主要介紹了java隨機(jī)生成一個(gè)名字和對(duì)應(yīng)拼音的方法,涉及java針對(duì)數(shù)組及隨機(jī)數(shù)操作的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • Java 利用遞歸實(shí)現(xiàn)鏈表的歸并排序

    Java 利用遞歸實(shí)現(xiàn)鏈表的歸并排序

    這篇文章主要介紹了Java 如何利用遞歸實(shí)現(xiàn)鏈表的歸并排序,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-09-09
  • Java實(shí)現(xiàn)的n階曲線擬合功能示例

    Java實(shí)現(xiàn)的n階曲線擬合功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的n階曲線擬合功能,結(jié)合實(shí)例形式分析了Java基于矩陣的多項(xiàng)式曲線擬合相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • Java實(shí)現(xiàn)重定向過(guò)程中添加請(qǐng)求頭信息

    Java實(shí)現(xiàn)重定向過(guò)程中添加請(qǐng)求頭信息

    在Java中,我們經(jīng)常需要使用網(wǎng)絡(luò)請(qǐng)求來(lái)與服務(wù)器進(jìn)行通信,在進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí),有時(shí)我們需要在重定向過(guò)程中添加請(qǐng)求頭信息,本文將介紹如何使用Java在重定向過(guò)程中添加請(qǐng)求頭,并提供相應(yīng)的代碼示例,
    2023-10-10
  • 淺談Java實(shí)現(xiàn)分布式事務(wù)的三種方案

    淺談Java實(shí)現(xiàn)分布式事務(wù)的三種方案

    現(xiàn)在互聯(lián)網(wǎng)下,分布式和微服務(wù)橫行,難免會(huì)遇到分布式下的事務(wù)問(wèn)題,當(dāng)然微服務(wù)下可能沒(méi)有分布式事務(wù),但是很多場(chǎng)景是需要分布式事務(wù)的。下面就來(lái)介紹下什么是分布式事務(wù)和分布式事務(wù)的解決方案
    2021-06-06
  • java日期操作工具類(獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù))

    java日期操作工具類(獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù))

    這篇文章主要為大家詳細(xì)介紹了java日期操作工具類,包括獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù)等操作,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評(píng)論

石景山区| 新平| 台江县| 卫辉市| 车险| 东源县| 开原市| 玛纳斯县| 区。| 天长市| 盈江县| 安康市| 铁岭县| 泰兴市| 寿光市| 咸丰县| 通城县| 永兴县| 梧州市| 榆中县| 肃南| 千阳县| 大丰市| 祁门县| 普兰店市| 侯马市| 唐海县| 称多县| 延边| 波密县| 浏阳市| 兴化市| 迭部县| 金川县| 濮阳市| 镇赉县| 湘西| 通山县| 安平县| 平昌县| 宁海县|