1. 程式人生 > 實用技巧 >【java】集合流式程式設計總結

【java】集合流式程式設計總結

在具體的介紹之前,先總結一波常用的寫法,有基礎的可以直接拿來用,沒有基礎的可以先跳過,看完下面的基礎再回來看

public static void main(String[] args) {
    List<User> userList = new ArrayList<>();
    userList.addAll(Arrays.asList(
            new User(1, 11, "張三"),
            new User(1, 11, "張三"),
            new User(2, 22, "李四"),
            
new User(1, 33, "王五"), new User(2, 44, "趙六"), new User(2, 44, "趙六"))); //----------------------------------------------中間操作---------------------------------------------- //【filter】從列表中篩選出性別為女的資料 List<User> filterUsage = userList.stream().filter(s->s.getSex() == 2).collect(Collectors.toList());
//結果:[User(sex=2, age=22, name=李四), User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)] System.out.println(filterUsage); //【distinct】從列表中去重 List<User> distinctUsage = userList.stream().distinct().collect(Collectors.toList()); //結果:[User(sex=1, age=11, name=張三), User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六)]
System.out.println(distinctUsage); //【sorted】按照年齡欄位從大到小重新排序 (從小到大就是s1.getAge()-s2.getAge()) List<User> sortedUsage = userList.stream().sorted((s1,s2)->s2.getAge()-s1.getAge()).collect(Collectors.toList()); //結果:[User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六), User(sex=1, age=33, name=王五), User(sex=2, age=22, name=李四), User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)] System.out.println(sortedUsage); //【limit】獲取前兩條資料 List<User> limitUsage = userList.stream().limit(2).collect(Collectors.toList()); //結果:[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)] System.out.println(limitUsage); //【skip】跳過前兩條,之後獲取前三條資料 List<User> skipUsage = userList.stream().skip(2).limit(3).collect(Collectors.toList()); //結果:[User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六)] System.out.println(skipUsage); //【map】獲取所有人的姓名 List<String> mapUsage = userList.stream().map(User::getName).collect(Collectors.toList()); //結果:[張三, 張三, 李四, 王五, 趙六, 趙六] System.out.println(mapUsage); //【flatMap】 //【Collectors工具類一些常用方法】 //【maxBy】獲取集合中年齡最大的物件資訊 User maxByUsage = userList.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get(); //結果:User(sex=2, age=44, name=趙六) System.out.println(maxByUsage); //【minBy】獲取集合中年齡最小的物件資訊 User minByUsage = userList.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge())).get(); //結果:User(sex=1, age=11, name=張三) System.out.println(minByUsage); //【joining】拼接集合中所有的使用者名稱稱---直接拼接 String joiningUsage = userList.stream().map(User::getName).collect(Collectors.joining()); //結果:張三張三李四王五趙六趙六 System.out.println(joiningUsage); //拼接中間加上逗號 String joiningUsage2 = userList.stream().map(User::getName).collect(Collectors.joining(",")); //結果:張三,張三,李四,王五,趙六,趙六 System.out.println(joiningUsage2); //拼接中間加上逗號,兩邊加上前後綴 String joiningUsage3 = userList.stream().map(User::getName).collect(Collectors.joining(",","[","]")); //結果:[張三,張三,李四,王五,趙六,趙六] System.out.println(joiningUsage3); //【counting】獲取集合中物件的數量 Long countingUsage = userList.stream().collect(Collectors.counting()); //結果:6 System.out.println(countingUsage); //【summingInt】獲取集合中所有物件年齡的和 int summingIntUsage = userList.stream().collect(Collectors.summingInt(User::getAge)); //結果:165 System.out.println(summingIntUsage); //【averagingInt】獲取集合中所有物件年齡的平均值 Double averagingIntUsage = userList.stream().collect(Collectors.averagingInt(User::getAge)); //結果:27.5 System.out.println(averagingIntUsage); //【summarizingInt】獲取集合中所有物件的數量/和/最大值/最小值/平均值等資訊 IntSummaryStatistics summarizingIntUsage = userList.stream().collect(Collectors.summarizingInt(User::getAge)); //結果:IntSummaryStatistics{count=6, sum=165, min=11, average=27.500000, max=44} System.out.println(summarizingIntUsage); //----------------------------------------------最終操作---------------------------------------------- //【collect】 //這裡不做演示,上面的所有例子中都有用到 //【reduce】將集合中的所有性別欄位的值按照相加的規則求乘積 Integer reduceUsage = userList.stream().map(User::getSex).reduce((s1, s2) -> s1 * s2).get(); //結果:8 System.out.println(reduceUsage); //【count】求集合中物件的數量 long countUsage = userList.stream().count(); //結果:6 System.out.println(countUsage); //【forEach】遍歷出所有的物件的名稱 Consumer<String> action = System.out::println; //結果:張三 張三 李四 王五 趙六 趙六 userList.stream().map(User::getName).forEach(action); //【max&min】獲取集合中所有物件中年齡的最大值和最小值 Integer maxUsage = userList.stream().map(User::getAge).max(Integer::compareTo).get(); //結果:44 System.out.println(maxUsage); Integer minUsage = userList.stream().map(User::getAge).min(Integer::compareTo).get(); //結果:11 System.out.println(minUsage); //【Matching -> allMatch、anyMatch、noneMatch】 //allMatch:只有當流中所有的元素,都匹配指定的規則,才會返回true boolean allMatchUsage = userList.stream().map(User::getAge).allMatch(e -> e >= 44); //結果:false System.out.println(allMatchUsage); //anyMatch:只要流中有任意的資料,滿足指定的規則,都會返回true boolean anyMatchUsage = userList.stream().map(User::getAge).anyMatch(e -> e <= 11); //結果:true System.out.println(anyMatchUsage); //noneMatch:只有當流中所有的元素,都不滿足指定的規則,才會返回true boolean noneMatchUsage = userList.stream().map(User::getAge).noneMatch(e -> e < 11); //結果:true System.out.println(noneMatchUsage); //【find--> findFirst、findAny】【parallelStream並行流、stream序列流】 //findFirst:從流中獲取開頭第一個元素 User user = userList.stream().findFirst().get(); //結果:User(sex=1, age=11, name=張三) System.out.println(user); User user2 = userList.parallelStream().findFirst().get(); //結果:User(sex=1, age=11, name=張三) System.out.println(user2); //findAny:單執行緒是獲取第一個元素,多執行緒可能不一樣 User user3 = userList.stream().findAny().get(); //結果:User(sex=1, age=11, name=張三) System.out.println(user3); User user4 = userList.parallelStream().findAny().get(); //結果:User(sex=1, age=33, name=王五) System.out.println(user4); //【IntStream+summaryStatistics】獲取int陣列中的最大值 //1.準備一個int陣列作為資料來源 int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; //2.讀取資料到流中,獲取IntStream物件 IntStream intStream = Arrays.stream(array); //兩種方法:(不能一起用,因為是中間操作) //1. 直接通過IntStream來獲取 //System.out.println(intStream.max().getAsInt()); //2. 通過IntSummaryStatistics,裡面包括最大/最小/平均/數量等方法 IntSummaryStatistics intSummaryStatistics = intStream.summaryStatistics(); //結果:9 System.out.println(intSummaryStatistics.getMax()); }
View Code

一、集合流的簡介

1. 集合的流式程式設計的簡介

Stream是JDK1.8之後出現的新特性,也是JDK1.8新特性中最值得學習的兩種新特性之一(另一個是lambda表示式)Stream是對集合操作的增強,流不是集合的元素,不是一種資料結構,不負責資料的儲存的。流更像是一個迭代器,可以單向的遍歷一個集合中的每一個元素,並且不可迴圈。

2. 為什麼要使用集合的流式程式設計

有些時候,對集合中的元素進行操作的時候,需要使用到其他操作的結果。在這個過程中,集合的流式程式設計可以大幅度的簡化程式碼的數量。將資料來源中的資料,讀取到一個流中,可以對這個流中的資料進行操作(刪除、過濾、對映...)。每次的操作結果也是一個流物件,可以對這個流再進行其它的操作。

3. 使用流式程式設計的步驟

通常情況下,對集合中的資料使用流式程式設計,需要經過以下三步:

(1)獲取資料來源,將資料來源中的資料讀取到流中
(2)對流中的資料進行各種各樣的處理
(3)對流中的資料進行整合處理

在上述三個過程:

(1)過程2中,有若干方法,可以對流中的資料進行各種各樣的操作,並且返回流物件本身,這樣的操作,被稱為中間操作
(2)過程3中,有若干方法,可以對流中的資料進行各種處理,並關閉流,這樣的操作,被稱為最終操作

在中間操作和最終操作中,基本上所有的方法引數都是函式式介面,可以使用lambda表示式來實現。使用集合的流式程式設計,來簡化程式碼量。

二、資料來源的獲取

1. 資料來源的簡介

資料來源,顧名思義,就是流中的資料的來源,是集合的流式程式設計的第一步,將資料來源中的資料讀取到流中,進行處理。注意:將資料讀取到流中進行處理的時候,與資料來源中的資料沒有關係。也就是說,中間操作對流中的資料進行處理、過濾、對映、排序...是不會影響到資料來源中的資料的。

2. 資料來源的獲取

這個過程,其實是將一個容器中的資料,讀取到一個流中,因此無論什麼容器作為資料來源,讀取到流中的方法返回值一定是一個Stream。

public static void main(String[] args) throws Exception{
    //將集合作為資料來源,讀取集合中的資料到一個流中
    collectionDataSource();
    //將陣列作為資料來源,讀取陣列中的資料到一個流中(使用引用資料型別)
    arrayDataSource();
    //將陣列作為資料來源,讀取陣列中的資料到一個流中(使用基本資料型別)
}

//將集合作為資料來源,讀取集合中的資料到一個流中
public static void collectionDataSource(){
    //1.例項化一個集合
    List<Integer> list = new ArrayList<>();
    //2.填充元素
    Collections.addAll(list,0,1,2,3,4,5,6,7,8,9);
    //3.讀取集合中的資料,將其讀取到流中
    //Stream<Integer> stream = list.stream();//同步流
    Stream<Integer> integerStream = list.parallelStream();//併發流
    //4.輸出stream
    System.out.println(integerStream);//java.util.stream.ReferencePipeline$Head@4554617c
}

//將陣列作為資料來源,讀取陣列中的資料到一個流中
public static void arrayDataSource(){
    //1.例項化一個數組
    Integer[] array = new Integer[]{0,1,2,3,4,5,6,7,8,9};
    //2.讀取陣列中的資料到流中,得到一個流物件
    Stream<Integer> stream = Arrays.stream(array);
    //3.輸出Stream
    System.out.println(stream);
}

//將陣列作為資料來源,讀取陣列中的資料到一個流中
//集合中只能存引用資料型別,但是陣列中不用
public static void arrayDataSource2(){
    //1.例項化一個數組
    int[] array = new int[]{0,1,2,3,4,5,6,7,8,9};
    //2.讀取陣列中的資料到流中,得到一個流物件
    IntStream stream = Arrays.stream(array);
    //3.輸出Stream
    System.out.println(stream);
}

三、最終操作

將流中的資料整合到一起,可以存入一個集合,也可以直接對流中的資料進行遍歷,資料統計...通過最終操作,需要掌握如何從流中提取出來我們想要的資訊。

注意事項:最終操作,在執行結束之後,會關閉這個流,流中的所有資料都會被銷燬,如果使用一個已經關閉了的流,會出現異常。

最終操作包括:collect、reduce、count、forEach、max&min、Matching、find、IntStream等。

1. collect

將流中的資料收集到一起,對這些資料進行一些處理。最常見的處理,就是將流中的資料存入一個集合。collect方法的引數,是一個collector介面,而且這個介面並不是一個函式式介面,實現這個介面,可以自定義收集的規則。但是,絕大部分情況下,不需要自定義。
直接使用Collectors工具類提供的方法即可。

public class FinalOperation {
    public static void main(String[] args) {
        collectUsage();
    }

    //最終操作:collect將流中的資料整合起來,最常見的處理是:讀取流中的資料,整合到一個容器中,得到一個集合。
    public static void collectUsage(){
        //1.讀取資料來源
        Stream<Integer> dataSource = getDataSource();
        //2.流中的資料的聚合
        //List<Integer> list = dataSource.collect(Collectors.toList());
        //System.out.println(list);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        //Set<Integer> set = dataSource.collect(Collectors.toSet());
        //System.out.println(set);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        //Map<String, Integer> map = dataSource.collect(Collectors.toMap(i -> i.toString(), i -> i));//i.toString作為鍵 i作為值
        Map<String, Integer> map = dataSource.collect(Collectors.toMap(Object::toString, i -> i));//i.toString作為鍵 i作為值
        System.out.println(map);//{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9}
    }

    //資料來源的獲取,從一個容器中獲取資料來源中的資料(得到一個Stream物件)
    public static Stream<Integer> getDataSource(){
        //1.準備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向資料來源中新增資料
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取資料來源中的資料,得到Stream物件
        return dataSource.stream();
    }
}
View Code

2. reduce

將流中的資料按照一定的規則聚合起來。將流的元素,逐一帶入這個方法中,進行運算。最終的運算結果,得到的其實是一個Optional型別,需要使用get()獲取到裡面的資料

public class FinalOperation {
    public static void main(String[] args) {
        reduceUsage();
    }

    public static void reduceUsage(){
        //1.讀取資料來源,得到流物件
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 (這裡有兩個引數,實現了從0到9的和的求值 即p1=0 p2=1 和的結果為1作為p1 再跟p2=2相加,以此類推)
        Integer num = dataSource.reduce((p1, p2) -> p1 + p2).get();
        //Integer num = dataSource.reduce(Integer::sum).get();
        //3.輸出
        System.out.println(num);//45
    }

    //資料來源的獲取,從一個容器中獲取資料來源中的資料(得到一個Stream物件)
    public static Stream<Integer> getDataSource(){
        //1.準備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向資料來源中新增資料
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取資料來源中的資料,得到Stream物件
        return dataSource.stream();
    }
}
View Code

3. count

統計流中的元素數量

public class FinalOperation {
    public static void main(String[] args) {
        countUsage();
    }

    public static void countUsage(){
        //1.讀取資料來源,得到流物件
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 獲取元素數量
        Long num = dataSource.count();
        //3.輸出
        System.out.println(num);//10
    }

    //資料來源的獲取,從一個容器中獲取資料來源中的資料(得到一個Stream物件)
    public static Stream<Integer> getDataSource(){
        //1.準備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向資料來源中新增資料
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取資料來源中的資料,得到Stream物件
        return dataSource.stream();
    }
}
View Code

4. forEach

迭代、遍歷流中的資料

public class FinalOperation {
    public static void main(String[] args) {
        forEachUsage();
    }

    public static void forEachUsage(){
        //1.讀取資料來源,得到流物件
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 遍歷流中的資料 輸出
        dataSource.forEach(System.out::print);//0123456789
    }

    //資料來源的獲取,從一個容器中獲取資料來源中的資料(得到一個Stream物件)
    public static Stream<Integer> getDataSource(){
        //1.準備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向資料來源中新增資料
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取資料來源中的資料,得到Stream物件
        return dataSource.stream();
    }
}
View Code

5. max&min

獲取流中的最大/最小元素

public class FinalOperation {
    public static void main(String[] args) {
        maxAndMinUsage();
    }

    //按照執行的物件比較的規則去進行大小的比較,然後得出流中最大、最小的資料
    public static void maxAndMinUsage(){
        //1.讀取資料來源,得到流物件
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 獲取流中的最大、最小值
        //Integer max = dataSource.max(Integer::compareTo).get();
        //System.out.println(max);//9
        Integer min = dataSource.min(Integer::compareTo).get();
        System.out.println(min);//0
    }

    //資料來源的獲取,從一個容器中獲取資料來源中的資料(得到一個Stream物件)
    public static Stream<Integer> getDataSource(){
        //1.準備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向資料來源中新增資料
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取資料來源中的資料,得到Stream物件
        return dataSource.stream();
    }
}
View Code

6. Matching

allMatch:只有當流中所有的元素,都匹配指定的規則,才會返回true
anyMatch:只要流中有任意的資料,滿足指定的規則,都會返回true
noneMatch:只有當流中所有的元素,都不滿足指定的規則,才會返回true

public static void main(String[] args) {
    matchingUsage();
}

public static void matchingUsage(){
    //1.讀取資料來源,獲取Stream物件
    Stream<Integer> dataSource = getDataSource();
    //2.匹配的操作
    //boolean b = dataSource.allMatch(e -> e>0);
    //System.out.println(b);//false 因為不是集合中所有的元素都大於0 還有一個等於0
    //boolean b = dataSource.anyMatch(e -> e >= 9);
    //System.out.println(b);//true
    boolean b = dataSource.noneMatch(e -> e > 9);
    System.out.println(b);//true
}

//資料來源的獲取,從一個容器中獲取資料來源中的資料(得到一個Stream物件)
public static Stream<Integer> getDataSource(){
    //1.準備一個容器
    List<Integer> dataSource = new ArrayList<>();
    //2.向資料來源中新增資料
    Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    //3.讀取資料來源中的資料,得到Stream物件
    return dataSource.stream();
}
View Code

7. find

findFirst:從流中獲取一個元素(是獲取的開頭元素)
findAny:從流中獲取一個元素(一般情況下,是獲取的開頭的元素)
這兩個方法,絕大部分情況下,是完全相同的,但是在多執行緒環境下,返回結果可能不一樣

public static void main(String[] args) {
    findUsage();
}

public static void findUsage(){
    //1.例項化一個集合
    ArrayList<Integer> dataSource = new ArrayList<>();
    Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    //2.findFirst演示
    //Integer integer = dataSource.stream().findFirst().get();//序列流
    //Integer integer = dataSource.parallelStream().findFirst().get();//並行流
    //System.out.println(integer);//序列流或者是並行流結果都是0
    //3.findAny演示
    //Integer integer = dataSource.stream().findAny().get();//序列流
    Integer integer = dataSource.parallelStream().findAny().get();//並行流
    System.out.println(integer);//序列流是0、並行流結果為6  即不一定是0
}
View Code

8. IntStream

主要可以實現獲取流中int型別資料的最大值、最小值、平均值、和、數量
還可以獲取到一個對流中資料的分析結果(即一次獲取所有型別的值)

public static void main(String[] args) {
    intStreamUsage();
}

public static void intStreamUsage(){
    //1.準備一個int陣列作為資料來源
    int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //2.讀取資料到流中,獲取IntStream物件
    IntStream stream = Arrays.stream(array);
    //3.輸出
    //System.out.println(stream.max().getAsInt());//獲取最大值     9
    //System.out.println(stream.min().getAsInt());//獲取最小值     0
    //System.out.println(stream.sum());//獲取和      45
    //System.out.println(stream.count());//獲取流中資料個數   10
    //System.out.println(stream.average().getAsDouble());//獲取流中資料的平均值   4.5
    //4.獲取到一個對流中資料的分析結果(即一次獲取所有型別的值)
    IntSummaryStatistics intSummaryStatistics = stream.summaryStatistics();
    System.out.println("最大值:"+intSummaryStatistics.getMax()+" 最小值:"+intSummaryStatistics.getMin());//最大值:9 最小值:0
    System.out.println("平均值:"+intSummaryStatistics.getAverage()+" 和:"+intSummaryStatistics.getSum());//平均值:4.5 和:45
    System.out.println("數量:"+intSummaryStatistics.getCount());//數量:10
}
View Code

四、中間操作

將資料從資料來源中讀取到流中,就是對流中的資料進行各種各樣的操作、處理。中間操作可以連續操作,每一個操作的返回值都是一個Stream物件,可以繼續進行其他的操作,直到最終操作。

中間操作主要分為:filter、distinct、sorted、limit&skip、map&flatMap、Collections工具類

1. filter

條件過濾,僅保留流中滿足指定條件的資料,其他不滿足的資料都會被刪除。

//學生類:儲存於集合中的資料型別
private static class Student{
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    //這裡省略getter、setter、toString方法
}

public static void main(String[] args) {
    filterUsage();
}

public static void filterUsage(){
    //1. 獲取資料來源
    Stream<Student> dataSource = getDataSource();
    //2. 過濾掉集合中成績不合格的學生資訊
    dataSource.filter(s -> s.getScore()>=60).forEach(System.out::println);
    //Student{name='xiaoming', age=18, score=100}
    //Student{name='xiaoming', age=19, score=90}
    //Student{name='xiaoming', age=20, score=80}
    //Student{name='xiaoming', age=21, score=70}
    //Student{name='xiaoming', age=22, score=60}
}

//讀取資料來源,將集合中儲存的資料,讀取到資料來源中
public static Stream<Student> getDataSource(){
    //1.例項化一個集合,存Student物件
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.新增若干資料
    Collections.addAll(arrayList,
                       new Student("xiaoming",18,100),
                       new Student("xiaoming",19,90),
                       new Student("xiaoming",20,80),
                       new Student("xiaoming",21,70),
                       new Student("xiaoming",22,60),
                       new Student("xiaoming",23,50),
                       new Student("xiaoming",24,40)
                      );
    //3.讀取資料來源,得到Stream物件
    return arrayList.stream();
}
View Code

2. distinct

去除集合中重複的元素,這個方法沒有引數,去重的規則與HashSet相同。
(1)比較兩個物件的hashcode
(2)使用equals再來對比一下
這裡要注意:實體類中需要重寫hashcode和equals方法,否則去重可能不會生效

//學生類:儲存於集合中的資料型別
private static class Student{
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    //這裡省略getter、setter、toString、hashcode、equals方法
}

public static void main(String[] args) {
    distinctUsage();
}


public static void distinctUsage(){
    //1. 獲取資料來源
    Stream<Student> dataSource = getDataSource();
    //2. 去重 要注意實體類Student中需要重寫equals和hashCode方法,否則去重不會生效
    dataSource.distinct().forEach(System.out::println);
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming2', age=20, score=80}
    //Student{name='xiaoming3', age=21, score=70}
    //Student{name='xiaoming4', age=22, score=60}
    //Student{name='xiaoming5', age=23, score=50}
    //Student{name='xiaoming6', age=24, score=40}

}

//讀取資料來源,將集合中儲存的資料,讀取到資料來源中
public static Stream<Student> getDataSource(){
    //1.例項化一個集合,存Student物件
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.新增若干資料
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取資料來源,得到Stream物件
    return arrayList.stream();
}
View Code

3. sorted

對流中的資料進行排序
(1)無參:sorted():將流中的資料,按照其對應的類實現的Comparable介面提供的比較規則進行排序
(2)有參:sorted(Comparator<T> comparator):將流中的資料,按照引數介面提供的比較規則進行排序

private static class Student implements Comparable<Student>{
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public int compareTo(Student o) {
        return score-o.score;
    }
    //這裡省略getter、setter、toString、hashcode、equals方法
}

public static void main(String[] args) {
    sortedUsage();
}


public static void sortedUsage(){
    //1. 獲取資料來源
    Stream<Student> dataSource = getDataSource();
    //2. 將流中的資料進行排序 (注意實體類要注意實現Comparable介面並重寫compareTo方法,否則會報錯)
    //dataSource.sorted().forEach(System.out::println);
    //Student{name='xiaoming6', age=24, score=40}
    //Student{name='xiaoming5', age=23, score=50}
    //Student{name='xiaoming4', age=22, score=60}
    //Student{name='xiaoming3', age=21, score=70}
    //Student{name='xiaoming2', age=20, score=80}
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming1', age=18, score=100}
    //3. 對流中的資料按照自定義的規則進行排序 (按照年齡升序排列)
    dataSource.sorted((s1,s2)->s1.getAge()-s2.getAge()).forEach(System.out::println);
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming2', age=20, score=80}
    //Student{name='xiaoming3', age=21, score=70}
    //Student{name='xiaoming4', age=22, score=60}
    //Student{name='xiaoming5', age=23, score=50}
    //Student{name='xiaoming6', age=24, score=40}
}

//讀取資料來源,將集合中儲存的資料,讀取到資料來源中
public static Stream<Student> getDataSource(){
    //1.例項化一個集合,存Student物件
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.新增若干資料
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取資料來源,得到Stream物件
    return arrayList.stream();
}
View Code

4. limit&skip

limit:限制,擷取流中指定數量的元素 skip:跳過流中的指定數量的元素 經常放在一起用

//實體類省略,參考上面即可

public static void main(String[] args) {
     limitAndSkipUsage();
 }


public static void limitAndSkipUsage(){
    //1. 獲取資料來源
    Stream<Student> dataSource = getDataSource();
    //2. 獲取成績的前5名
    //        dataSource.distinct()
    //                .sorted((s1,s2)->s2.getScore()-s1.getScore())
    //                .limit(5)
    //                .forEach(System.out::println);
    //3. 獲取成績為3-5名的
    dataSource.distinct()
        .sorted((s1,s2)->s2.getScore()-s1.getScore())
        .limit(5)
        .skip(2)
        .forEach(System.out::println);
}

//讀取資料來源,將集合中儲存的資料,讀取到資料來源中
public static Stream<Student> getDataSource(){
    //1.例項化一個集合,存Student物件
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.新增若干資料
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取資料來源,得到Stream物件
    return arrayList.stream();
}
View Code

5. map&flatMap

對流中的資料進行對映,用新的資料替換舊的資料

map最主要,就是來做元素的替換,其實map是一個元素的對映(將流中每一個元素替換成指定的元素)

flatMap也是元素的對映,flatMap是扁平化對映

扁平化對映:一般用在map對映完成後,流中的資料是一個容器,而我們需要對容器中的資料進行處理 此時使用扁平化對映,可以將流中的容器中的資料,直接讀取到流中

案例1:

public static void main(String[] args) {
    mapUsage();
}


public static void mapUsage(){
    //1. 獲取資料來源
    Stream<Student> dataSource = getDataSource();
    //2. 實際需求:獲取所有學生的名字
    //dataSource.map(Student::getName).forEach(System.out::println);
    //dataSource.map(s->s.getName()).forEach(System.out::println);
    //3. 實際需求:獲取所有學生的成績 注意:泛型中不能是基本資料型別,只能是包裝類 即下面的返回值應該為Stream<Integer>
    //dataSource.map(Student::getScore).forEach(System.out::println);
    //4. 實際需求:獲取所有學生的成績
    IntSummaryStatistics intSummaryStatistics = dataSource.mapToInt(Student::getScore).summaryStatistics();
    System.out.println(intSummaryStatistics.getMax());
}

//讀取資料來源,將集合中儲存的資料,讀取到資料來源中
public static Stream<Student> getDataSource(){
    //1.例項化一個集合,存Student物件
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.新增若干資料
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取資料來源,得到Stream物件
    return arrayList.stream();
}
View Code

案例2:

public static void main(String[] args) {
    mapUsage();
}

public static void mapUsage(){
    //1.例項化一個字串陣列
    String[] array = {"hello","world"};
    //2.將字串陣列中的資料讀取到流中
    Stream<String> stream = Arrays.stream(array);
    //3.需求:統計字串陣列中所有出現的字元
    //stream.map(String::toCharArray).forEach(e->System.out.println(Arrays.toString(e)));
    //結果為 [h, e, l, l, o]  [w, o, r, l, d] 兩個陣列 不符合我們的要求
    stream.map(s->s.split(""))
        .flatMap(Arrays::stream)
        .distinct()
        .forEach(System.out::println);
    //結果為h e l o w r d
}
View Code

6. Collections工具類

Collectors是一個工具類,裡面封裝了很多方法,可以很方便的獲取到一個Collector介面的實現類物件,從而可以使用collect()方法,對流中的資料,進行各種各樣的處理、整合。
常用方法:
Collectors.toList()將流中的資料,聚合到一個List集合中
Collectors.toSet()將流中的資料,聚合到一個Set集合中
Collectors.toMap()將流中的資料,聚合到一個Map集合中
maxBy()按照指定的規則,找到流中最大的元素,等同於max
minBy()按照指定的規則,找到流中最小的元素,等同於min
joining()將流中的資料拼接成一個字串,注意:只能操作流中是String的資料
summingInt()將流中的資料,對映成int型別的資料,並求和
averagingInt()將流中的資料,對映成int型別的資料,並求平均值
summarizingInt()將流中的資料,對映成int型別的資料,並獲取描述資訊

public static void main(String[] args) {
    //1. 準備一個字串陣列,作為資料來源
    String[] dataSource = {"nihao","wo","shi","xxx"};
    //2. 讀取資料來源中的資料
    Stream<String> stream = Arrays.stream(dataSource);
    //3. joining方法,只適用於 Stream<String> 這種流
    //String collect = stream.collect(Collectors.joining());//拼接
    //System.out.println(collect);//nihaowoshixxx
    //String collect = stream.collect(Collectors.joining(","));//拼接 按照逗號分隔
    //System.out.println(collect);//nihao,wo,shi,xxx
    //tring collect = stream.collect(Collectors.joining(",","[","]"));//拼接 帶字首、字尾
    //System.out.println(collect);//[nihao,wo,shi,xxx]

    //4. summingInt
    Integer collect = stream.collect(Collectors.summingInt(String::length));
    System.out.println(collect);//13
}
View Code

持續更新!!!

注意:本篇文章大多數內容來自bilibili網站千鋒教育,地址:https://www.bilibili.com/video/BV1fT4y177ui?p=6 本篇文章僅用於個人學習和總結,如有侵權,聯絡刪除!