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

Java的Stream入門級(jí)教程

 更新時(shí)間:2025年10月31日 11:18:45   作者:不吃肘擊  
Java的Stream(流)是從Java?8?引入的一套面向集合數(shù)據(jù)的聲明式處理API,它讓你像寫“數(shù)據(jù)流水線”一樣,對(duì)一組元素做篩選、變換、聚合等操作,代碼更簡(jiǎn)潔、更可讀,本文給大家介紹Java的Stream入門級(jí)教程,感興趣的朋友跟隨小編一起看看吧

什么是Stream流

Java 的 Stream(流)是從 Java 8 引入的一套面向集合數(shù)據(jù)的聲明式處理API。它讓你像寫“數(shù)據(jù)流水線”一樣,對(duì)一組元素做篩選、變換、聚合等操作,代碼更簡(jiǎn)潔、更可讀。

核心特性

管道化source → 中間操作* → 終止操作

惰性求值:只有遇到終止操作才真正執(zhí)行。

無(wú)副作用:鼓勵(lì)函數(shù)式寫法,避免改動(dòng)外部可變狀態(tài)。

可并行parallelStream() 能并行處理(適合大數(shù)據(jù)量且拆分成本低的場(chǎng)景)。

Stream流不是數(shù)據(jù)本身,而是數(shù)據(jù)的視圖,且Stream不可重復(fù)使用,且基于函數(shù)式接口

Stream流的生命周期

Java中Stream流的生命周期分三個(gè)步驟創(chuàng)建 → 中間操作 → 終止操作即生成數(shù)據(jù),處理數(shù)據(jù)到最后執(zhí)行結(jié)果

創(chuàng)建流

源:流是基于數(shù)據(jù)源如集合,數(shù)組,文件創(chuàng)建的,數(shù)據(jù)源可以是集合,數(shù)組,生成器等

例子:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream();  // 創(chuàng)建流

中間操作

惰性執(zhí)行:中間操作是惰性求值的,他們不會(huì)立即執(zhí)行。而是返回一個(gè)新的流,只有遇到終止操作的時(shí)候,中間操作才會(huì)執(zhí)行。

例子:

Stream<Integer> evenNumbers = stream.filter(n -> n % 2 == 0)  // 中間操作
                                   .map(n -> n * n);          // 另一個(gè)中間操作

終止操作

觸發(fā)執(zhí)行:終止操作會(huì)觸發(fā)流的處理鏈執(zhí)行,一旦執(zhí)行終止操作,流就會(huì)被消耗掉,而不能再使用.終止操作是流處理的真正的啟動(dòng)器,他會(huì)返回一個(gè)最終的結(jié)果

int sum = evenNumbers.reduce(0, Integer::sum);  // 終止操作,執(zhí)行計(jì)算

流的關(guān)閉

一旦流被消耗掉就不能再被重新使用,當(dāng)要再次處理數(shù)據(jù)的時(shí)候就要?jiǎng)?chuàng)建一個(gè)新的流

在關(guān)閉流的資源上對(duì)于集合類的流就不需要顯示關(guān)閉但是對(duì)于文件流,網(wǎng)絡(luò)流等最好通過(guò)close()來(lái)關(guān)閉

Stream流的創(chuàng)建方式

list.stream()

從集合創(chuàng)建
Arrays.stream(array)從數(shù)組創(chuàng)建
Stream.of("A","B","C")從值創(chuàng)建
Files.lines(Path.get("file.txt"))從文件行創(chuàng)建
Stream.iterate(0,n->n+1),Stream.generate(Math::random)無(wú)限創(chuàng)建流

常見的中間操作

filter():過(guò)濾符合的條件stream.filter(s -> s.length() > 3)
map(Function)轉(zhuǎn)換每個(gè)元素或者是提取對(duì)象的某個(gè)是屬性。將原始流中的每個(gè)元素映射為另一個(gè)類型或值。例子:steam.map(String::toUpperCase)
flatMap(Function)扁平化處理,用于嵌套結(jié)構(gòu)例子:stream.flatMap(List::stream)
distinct()去重(基于equals()和hashCode()方法)例子:stream.distinct()
sorted()排序(自然排序或者是自定義排序)例子:stream.sorted(Comparator.reverseOrder())
liit(n)截取前n個(gè)元素例子:stream.limit(10)

skip(n)

跳過(guò)前n個(gè)元素stream.skip(5)

:

:

:


 

常用的終端操作

forEach(Consumer)遍歷每個(gè)元素stream.forEach(System.out::println)
collect(Collector)收集結(jié)果(轉(zhuǎn)為 List、Set、Map 等)stream.collect(Collectors.toList())
count()返回元素個(gè)數(shù)stream.count()
anyMatch(Predicate)是否有任意一個(gè)匹配stream.anyMatch(s -> s.contains("Java"))
allMatch(Predicate)是否全部匹配stream.allMatch(s -> s.length() > 3)
noneMatch(Predicate)是否沒(méi)有匹配stream.noneMatch(s -> s.isEmpty())
findFirst()獲取第一個(gè)元素stream.findFirst()
reduce(BinaryOperator)聚合操作(如求和)stream.reduce((a, b) -> a + b)

注意:中間操作可以有多個(gè),但是在一個(gè)stream流中流的創(chuàng)建和終止操作只能有一個(gè)

實(shí)戰(zhàn)用例

1.將一個(gè)對(duì)象列表中大于10歲的對(duì)象的名字提取出來(lái)

首先給定一個(gè)Person類(在實(shí)際開發(fā)中不建議將屬性定義為public,這里只是為了演示

public class Person {
    public String name;
    public int age;
    public String city;
    public Person(String name,int age,String city){
        this.name = name;
        this.age = age;
        this.city = city;
    }
}

代碼演示:

import java.util.List;
import java.util.stream.Collectors;
public class StreamTest {
    public static void main(String []str){
        List<Person> people = List.of(
                new Person("Alice", 23, "Beijing"),
                new Person("Bob", 17, "Shanghai"),
                new Person("Carol", 30, "Beijing")
        );
        //提取大于18歲的對(duì)象的名字
        List<String> collect = people.stream()//獲取源數(shù)據(jù)
                .filter(p -> p.age > 18)//過(guò)濾源數(shù)據(jù),滿足條件則true則就保留
                .map(person -> person.name)//做map映射就是將這個(gè)源數(shù)據(jù)中的每個(gè)數(shù)據(jù)轉(zhuǎn)換成另外一種數(shù)據(jù),
                // 在這里面就是將每個(gè)對(duì)象轉(zhuǎn)換成他們對(duì)應(yīng)的名字
                .collect(Collectors.toList());//收集處理后的數(shù)據(jù),通過(guò)列表的方式
        System.out.println(collect);
    }
}

2.分組統(tǒng)計(jì),將列表中不同城市的人的數(shù)量做統(tǒng)計(jì)

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamTest {
    public static void main(String []str){
        List<Person> people = List.of(
                new Person("Alice", 23, "Beijing"),
                new Person("Bob", 17, "Shanghai"),
                new Person("Carol", 30, "Beijing"),
                new Person("Dave", 25, "Shanghai"),
                new Person("Eve", 22, "Beijing")
        );
        Map<String, Long> collect = people.stream()//轉(zhuǎn)為流數(shù)據(jù)
                .collect(Collectors.groupingBy(Person::getCity, Collectors.counting()));
        //這個(gè)的作用是將這個(gè)流中的數(shù)據(jù)做一個(gè)分組,key是city,value是key對(duì)應(yīng)的數(shù)量Collectors.counting() 是一個(gè)下游收集器,用來(lái)統(tǒng)計(jì)分組后的元素?cái)?shù)量。
        //它返回一個(gè) Long 類型的值,表示每個(gè)分組中元素的數(shù)量。在這里,它會(huì)統(tǒng)計(jì)每個(gè)城市中有多少個(gè) Person 對(duì)象。
        System.out.println(collect);
    }
}

3.多級(jí)分組-分區(qū)(在城市分組的情況下判斷是否成年)

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamTest {
    public static void main(String []str){
        List<Person> people = List.of(
                new Person("Alice", 23, "Beijing"),
                new Person("Bob", 17, "Shanghai"),
                new Person("Carol", 30, "Beijing"),
                new Person("Dave", 25, "Shanghai"),
                new Person("Eve", 22, "Beijing")
        );
        Map<String, Map<Boolean, List<Person>>> collect = people.stream()
                .collect(Collectors.groupingBy(Person::getCity, Collectors.partitioningBy(p -> p.age > 18)));
                //這里面的Collectors.groupingBy是將收集的數(shù)據(jù)進(jìn)行分組根據(jù)city屬性,他收集出來(lái)就是一個(gè)map,但是這個(gè)map的value不是一個(gè)值
        //而是一個(gè)對(duì)象這個(gè)對(duì)象是一個(gè)分區(qū)的函數(shù)partitioningBy他會(huì)將value又分成一個(gè)map將滿足條件的放一組,不滿足的放一組來(lái)形成一個(gè)map
        System.out.println(collect);
    }

4.聚合reduce

在java中的stream流的reduce方法是一個(gè)游泳的規(guī)約操作,將流中的元素反復(fù)結(jié)合起來(lái)最后得到一個(gè)值

reduce求和

import java.util.Arrays;
import java.util.List;
public class StreamTest {
    public static void main(String []str){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        int sum = numbers.stream()
                .reduce(0, (a, b) -> a + b);  // 0 是初始值,(a, b) -> a + b 是累加器
        System.out.println(sum);  // 輸出 15
    }
}

reduce求最大值

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = numbers.stream()
                               .reduce(Integer::max);  // 使用 Integer::max 方法引用
max.ifPresent(System.out::println);  // 輸出 5

在求最大值的時(shí)候就不需要初始值了

reduce拼接字符串

List<String> words = Arrays.asList("Java", "is", "awesome");
String result = words.stream()
                     .reduce("", (a, b) -> a + " " + b);  // 初始值為空字符串
System.out.println(result);  // 輸出 "Java is awesome"

5.統(tǒng)計(jì)年齡總數(shù)

IntSummaryStatistics stats = people.stream()
    .collect(Collectors.summarizingInt(Person::age));
// stats.getCount()/getSum()/getMin()/getMax()/getAverage()

6.自定義排序

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamTest {
    public static void main(String []str){
        List<Person> people = List.of(
                new Person("Alice", 23, "Beijing"),
                new Person("Bob", 17, "Shanghai"),
                new Person("Carol", 30, "Beijing"),
                new Person("Dave", 25, "Shanghai"),
                new Person("Eve", 22, "Beijing")
        );
        Comparator<Person> byCityThenAge = Comparator
                .comparing(Person::getCity, Comparator.nullsLast(String::compareTo))//定義比較類先是通過(guò)city排序,對(duì)于null的排到最后
                .thenComparingInt(Person::getAge);//然后通過(guò)年齡進(jìn)行比較
        List<Person> sorted = people.stream()
                .sorted(byCityThenAge)//通過(guò)比較類進(jìn)行排序
                .collect(Collectors.toList());
        System.out.println(sorted);
    }
}

怎么使用Comparator

Comparator 是 Java 中用于比較對(duì)象的接口,常用于排序操作。它定義了如何對(duì)對(duì)象進(jìn)行排序,并且可以自定義排序的規(guī)則??梢酝ㄟ^(guò) Comparator 來(lái)指定對(duì)象之間的比較邏輯,并且與 Collections.sort() 或 Stream.sorted() 等方法配合使用。

Comparator接口常用方法:

  • compare(T o1, T o2):比較兩個(gè)對(duì)象 o1o2,返回一個(gè)整數(shù),通常為:
    • 負(fù)整數(shù):表示 o1 小于 o2
    • 零:表示 o1 等于 o2
    • 正整數(shù):表示 o1 大于 o2
  • reversed():返回一個(gè)逆序的比較器,反轉(zhuǎn)當(dāng)前比較器的排序順序。
  • thenComparing(Comparator<? super T> other):鏈?zhǔn)秸{(diào)用,可以在現(xiàn)有排序規(guī)則基礎(chǔ)上,添加一個(gè)新的排序規(guī)則,用于次級(jí)排序(如果主排序條件相等)。
  • comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator):根據(jù)指定的鍵進(jìn)行排序,通常配合 Function 使用,從對(duì)象中提取出需要排序的字段。

多條件排序

List<Person> people = Arrays.asList(
    new Person("John", 25),
    new Person("Alice", 30),
    new Person("Bob", 20)
);

// 按名字排序,如果名字相同再按年齡排序
people.sort(Comparator.comparing(Person::getName)
                      .thenComparing(Person::getAge));

逆序排序

// 按年齡降序排序
people.sort(Comparator.comparing(Person::getAge).reversed());

使用 Comparator.nullsLast() 處理 null 值

List<String> strings = Arrays.asList("apple", "banana", null, "cherry", null);
strings.sort(Comparator.nullsLast(Comparator.naturalOrder())); // 排序時(shí),null 值排在最后
strings.forEach(System.out::println);

使用Comparing排序

// 按年齡排序,使用靜態(tài)方法 Comparator.comparing
people.sort(Comparator.comparing(Person::getAge)); // 按年齡升序

使用Lambda表達(dá)式排序

// 使用 Lambda 表達(dá)式簡(jiǎn)化比較邏輯
Collections.sort(people, (p1, p2) -> Integer.compare(p1.getAge(), p2.getAge())); // 按年齡升序

Stream流的優(yōu)勢(shì)?

1.簡(jiǎn)潔性和可讀性

  • 更簡(jiǎn)潔的代碼:Stream API 使用鏈?zhǔn)讲僮?,減少了顯式的循環(huán)和條件判斷,使代碼更簡(jiǎn)潔、易懂。
  • 函數(shù)式編程:通過(guò) mapfilter、reduce 等函數(shù)式操作,代碼變得更具聲明性,表示你想要做什么,而不是如何做,從而提高了可讀性。

2.避免顯式的循環(huán)

  • 不再手動(dòng)管理迭代器:Stream API 隱藏了迭代的細(xì)節(jié),減少了手動(dòng)編寫 for 循環(huán)或 Iterator 的代碼。這讓代碼更直觀、更符合直覺。

3.并行化和性能優(yōu)化

  • 并行流:Stream API 支持非常方便的并行處理,幾乎無(wú)需修改代碼就能讓程序利用多核處理器進(jìn)行并行計(jì)算,從而提高處理大量數(shù)據(jù)時(shí)的性能。
  • 并行流優(yōu)勢(shì):特別適合處理大規(guī)模數(shù)據(jù)集或計(jì)算密集型任務(wù),自動(dòng)進(jìn)行任務(wù)分解和并行處理,無(wú)需開發(fā)者顯式管理線程池。

4.惰性計(jì)算和延遲求值

  • 惰性求值:Stream 中的許多操作(如 filter, map, flatMap 等)是惰性計(jì)算的,即只有當(dāng)終止操作(如 collect, forEach, reduce)觸發(fā)時(shí),流中的操作才會(huì)執(zhí)行。
  • 只有當(dāng) collect() 被調(diào)用時(shí),filtermap 才會(huì)執(zhí)行,從而避免了中間計(jì)算的浪費(fèi)。

5.函數(shù)式編程思想

  • 高階函數(shù):Stream API 使用了函數(shù)式編程的概念,支持高階函數(shù)(可以將函數(shù)作為參數(shù)傳遞),這使得代碼更加靈活、可復(fù)用。

6.增強(qiáng)的可組合性和復(fù)用性

  • 組合多個(gè)操作:Stream API 允許你將多個(gè)操作組合成一個(gè)流水線,進(jìn)行一系列轉(zhuǎn)換、過(guò)濾、聚合等操作,這樣的鏈?zhǔn)秸{(diào)用使得代碼更具可組合性。

7.更好的錯(cuò)誤處理

  • 流的每一步都可自定義:Stream API 允許你對(duì)每一步進(jìn)行靈活的定制。例如,通過(guò) try-catch 語(yǔ)句、peek 等方法,可以更清晰地處理流的操作過(guò)程中的異常。
  • 你可以在流的操作過(guò)程中添加日志或調(diào)試信息,幫助更好地排查問(wèn)題。

8.數(shù)據(jù)轉(zhuǎn)換和聚合的高級(jí)功能

  • 復(fù)雜的數(shù)據(jù)轉(zhuǎn)換和聚合:Stream API 提供了非常強(qiáng)大的聚合功能(如 collect, reduce, groupingBy, partitioningBy, summarizingInt 等),可以幫助你輕松處理復(fù)雜的數(shù)據(jù)轉(zhuǎn)換和聚合任務(wù)。

9.可維護(hù)性和擴(kuò)展性

  • 代碼結(jié)構(gòu)清晰:使用 Stream API 可以讓數(shù)據(jù)處理代碼更為模塊化,容易理解,尤其是在面對(duì)復(fù)雜的過(guò)濾、映射、聚合等操作時(shí)。相對(duì)于傳統(tǒng)的多層循環(huán),Stream API 提供了更清晰的數(shù)據(jù)流轉(zhuǎn)過(guò)程,有助于后續(xù)的維護(hù)和擴(kuò)展。
  • 提升代碼質(zhì)量:流式操作鼓勵(lì)無(wú)副作用的編程(即不修改原始數(shù)據(jù)),這減少了 bug 的發(fā)生概率,并且提高了代碼的可測(cè)試性。

10.內(nèi)存使用優(yōu)化

  • 惰性加載:Stream 中的許多操作是惰性求值的,這意味著它們不會(huì)立即執(zhí)行,只有當(dāng)終止操作(如 collect)被調(diào)用時(shí),才會(huì)開始處理數(shù)據(jù)。這有助于避免在某些情況下的內(nèi)存浪費(fèi),尤其是在處理大型數(shù)據(jù)集時(shí)。

總結(jié):Stream API 的優(yōu)勢(shì)

相比于傳統(tǒng)的開發(fā)方式,Java Stream API 提供了以下幾大優(yōu)勢(shì):

  • 簡(jiǎn)潔性和可讀性:代碼更簡(jiǎn)潔,避免了顯式的循環(huán)。
  • 函數(shù)式編程支持:通過(guò)高階函數(shù)提供更高的靈活性和可重用性。
  • 并行處理:輕松使用 parallelStream() 實(shí)現(xiàn)并行處理,提高性能。
  • 惰性計(jì)算和延遲求值:避免不必要的計(jì)算,提高性能。
  • 豐富的聚合和轉(zhuǎn)換功能:提供強(qiáng)大的數(shù)據(jù)聚合、轉(zhuǎn)換、過(guò)濾等功能。
  • 函數(shù)式思維:鼓勵(lì)不修改數(shù)據(jù)的不可變式操作。

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

相關(guān)文章

最新評(píng)論

习水县| 永定县| 青川县| 湛江市| 介休市| 宝丰县| 开江县| 太保市| 工布江达县| 柞水县| 安多县| 宾阳县| 瓦房店市| 正镶白旗| 桦南县| 邯郸市| 荣成市| 连南| 临武县| 青岛市| 承德市| 黄冈市| 新乡县| 岑巩县| 铁岭市| 远安县| 镇安县| 团风县| 高邮市| 潮安县| 苍溪县| 桂阳县| 农安县| 永清县| 小金县| 哈巴河县| 保德县| 清流县| 娄烦县| 名山县| 连山|