還看不懂同事用的stream操作?看完這個你就明白了

前言

    其實最近自己看了不少的關於list流的操作文章,但是總覺得自己好像差點意思,只有有一天,自己好像忽然就明白了stream操作流的使用方式,不得不說,這個操作真的是行雲流水以及上手,現在感覺就是開心,非常開心
在這裏插入圖片描述

正文

1.準備數據

1.1 實體類

我們先來準備一個實體類,用來模擬我們正常業務開發中的實體類,也可以當做是map,下面的內容,我會一點一點來說明目前我所理解的流操作。
實體類代碼:

public class Student {

    private int number;

    private String name;

    private String clazz;

    private int score;



    public Student(int number, String name, String clazz, int score) {

        this.number = number;

        this.name = name;

        this.clazz = clazz;

        this.score = score;

    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "number=" + number +
                ", name='" + name + '\'' +
                ", clazz='" + clazz + '\'' +
                ", score=" + score +
                '}';
    }
}

1.2 操作測試類

準備數據的代碼

private static final List<Student> STUDENTS = create();

    private static final String CLAZZ1 = "軟件1班";

    private static final String CLAZZ2 = "軟件2班";

    private static List<Student> create() {

        Student s1 = new Student(2018008, "張揚", CLAZZ2, 66);

        Student s2 = new Student(2018005, "劉飛", CLAZZ1, 92);

        Student s3 = new Student(2018007, "李明", CLAZZ2, 42);

        Student s4 = new Student(2018006, "趙勇", CLAZZ2, 56);

        Student s5 = new Student(2018002, "王磊", CLAZZ1, 81);

        Student s6 = new Student(2018010, "牛娜", CLAZZ1, 78);

        List<Student> students = new ArrayList<>();

        students.add(s1);students.add(s2);students.add(s3);

        students.add(s4);students.add(s5);students.add(s6);

        return students;

    }

接下來我們要上作業了,在下面寫上我們的main方法,把需求寫在上面然後慢慢來。好了,來看一下這次我們的任務是哪些?

        public static void main(String[] args) {
        //方法1,獲取成績小於等於指定分數的全部學生
        //方法2,獲取指定班級,成績小於等於指定分數,的全部學生
        //方法3,獲取指定班級,成績小於等於指定分數,的全部學生的姓名。注意返回類型
        //方法4,按成績由低到高排序,返回全部學生
        //方法5,獲取指定班級,成績小於等於指定分數,成績由高到低排序,的全部學生
        //方法6,獲取指定班級,成績小於等於指定分數,成績由高到低排序,的全部學生的學號。注意返回類型
        //方法7,獲取指定班級,成績小於等於指定分數,的全部學生
    }

2.實現數據篩選

2.1 獲取成績小於等於指定分數的全部學生

先明確我們目的,要獲取成績小於等於指定分數,我們先假定這個分數爲75,那麼我們要使用流來進行操作,所以第一步,我們要先拿到這個list的流,那麼先寫出我們的代碼,

STUDENTS.stream()

這樣我們就拿到我們的流了,然後看需要,我們要拿到成績小於等於指定分數,也就是說我們是要在這些數據中做篩選了,那麼我點在上面的代碼添加.之後,會出現很多的方法,如下圖
在這裏插入圖片描述有些方法我們先不講,我們這次是要做篩選,所以我們選擇filter,那麼我們的代碼就變成了這樣

STUDENTS.stream().filter()

選擇了filter之後,我們要在filter裏面寫上我們的篩選條件,通常我們都是使用lambda表達式,我們的list中每一個對應都是一個Student,所以我們先用一個變量來標識這個student,這個變量,和你正常遍歷的使用for遍歷的i是一個功能,然後加入我們的篩選條件,成績小於等於75,然後我們的代碼就變成了

STUDENTS.stream().filter(student -> student.getScore() <= 75)

這樣我們的過濾就已經做完了,現在我們要拿到他返回的結果,我們在代碼後面繼續點,讓這個結果變成一個集合,所以我們需要把這個結果收集起來,所以我們選擇collect,這樣代碼就變成了

STUDENTS.stream().filter(student -> student.getScore() < 75).collect()

那麼我們以什麼樣的結果返回那,通常我們也是希望它能爲我們返回一個list,那麼我們在collect裏面告訴他,幫我返回list,我們藉助集合工具類,代碼就變成了

STUDENTS.stream().filter(student -> student.getScore() < 75).collect(Collectors.toList());

任務完成,加上分號,存儲變量打印輸出!看結果

在這裏插入圖片描述

在這裏插入圖片描述
下一個!!!

2.2 獲取指定班級,成績小於等於指定分數,的全部學生

這個需求,和上面什麼區別,我xxxxx,好吧,現在我們假定獲取軟件2班的同學吧(爲了偷懶就不讓他們選擇了,這個參數是可以傳遞的),那我們的代碼需要變得是哪裏,沒錯,就是我們的過濾條件,那我們怎麼改那,我直接雙&行不行,搞一下不就曉得了。來,上代碼

List<Student> collect2 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() <= 75).collect(Collectors.toList());

任務完成,加上分號,存儲變量打印輸出!看結果

在這裏插入圖片描述
在這裏插入圖片描述
怎麼又是你們!看了一眼數據,沒錯啊,就是你們,小於75的都是二班的!!!!
在這裏插入圖片描述
下一個!!!!

2.3 獲取指定班級,成績小於等於指定分數,的全部學生的姓名。注意返回類型

這個看樣子來新的需求了,不慌,看我搞定!
首先我們還是按照之前的數據來做過濾,那麼我們的代碼先寫成這個樣子

STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() <= 75)

這個時候我們已經做了過濾等級和班級,看他後面的需要,全部學生的姓名,那我們應該怎麼蒐集他的姓名呢,首先明確我們的目標,我們是要做收集對象的某一個屬性,filter肯定不對,foreach遍歷操作有點像,但是也不對,因爲foreach的操作時沒有返回值的(這個你試一下就知道了),那麼其他的方法名我們怎麼看都不太像,那就試一下map吧,裏面同樣寫出lambda表達式,我們獲取他的名稱,上代碼

List<String> collect3 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).map(student -> student.getName()).collect(Collectors.toList());

收集就一起寫上去了,看一下返回結果,好像是一個List 好像有戲,執行一下試一下

在這裏插入圖片描述
在這裏插入圖片描述
下一個!!!!

2.4 按成績由低到高排序,返回全部學生

這個簡單,我直接Arrays.sort(list.toArray)
等等,
在這裏插入圖片描述
我在說什麼,先看看我們的流又沒有提供排序功能吧,獲取流之後點一下,發現有一個sorted,嗯,像,那就試一下吧
所以我們代碼就變成了這樣
在這裏插入圖片描述
有兩個方法,一個需要傳遞比較器,一個不需要傳遞,看樣子不傳遞的應該就是默認的排序規則了吧,java默認的排序規則一般都是從小到大(實際上我也試了,是從小到大),student裏面沒有比較的方法,所以我們還是自己寫一個比較器吧,然後我們的代碼就變成了

List<Student> collect4 = STUDENTS.stream().sorted(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore()-o2.getScore();
            }
        }).collect(Collectors.toList());
        //打印輸出內容
        collect4.stream().forEach(student -> System.out.println(student));

看執行結果
在這裏插入圖片描述

在這裏插入圖片描述
下一個!!!!!!

2.5 獲取指定班級,成績小於等於指定分數,成績由高到低排序,的全部學生

這個就是2.2和2.4組合,代碼應該不難理解,先排序還是先過濾都可以,建議還是先過濾 。注意排序規則變了,所以我們要修改我們的比較器。上代碼了

List<Student> collect5 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).sorted(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getScore() - o1.getScore();
            }
        }).collect(Collectors.toList());

執行結果

在這裏插入圖片描述
在這裏插入圖片描述
下一個!!!!

2.6 獲取指定班級,成績小於等於指定分數,成績由高到低排序,的全部學生的學號。注意返回類型

這,這個2.4有什麼區別,就是多了一個比較嗎?過,下一個

        List<Integer> collect6 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).sorted(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getScore() - o1.getScore();
            }
        }).map(student -> student.getNumber()).collect(Collectors.toList());
        

在這裏插入圖片描述

2.7 獲取指定班級,成績小於等於指定分數,的全部學生

這個,怎麼感覺需求跟上面比還變簡單了呢,上代碼了

STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).collect(Collectors.toList());

在這裏插入圖片描述
附上完整版本代碼

public class StreamTest1 {
    private static final List<Student> STUDENTS = create();

    private static final String CLAZZ1 = "軟件1班";

    private static final String CLAZZ2 = "軟件2班";

    private static List<Student> create() {

        Student s1 = new Student(2018008, "張揚", CLAZZ2, 66);

        Student s2 = new Student(2018005, "劉飛", CLAZZ1, 92);

        Student s3 = new Student(2018007, "李明", CLAZZ2, 42);

        Student s4 = new Student(2018006, "趙勇", CLAZZ2, 56);

        Student s5 = new Student(2018002, "王磊", CLAZZ1, 81);

        Student s6 = new Student(2018010, "牛娜", CLAZZ1, 78);

        List<Student> students = new ArrayList<>();

        students.add(s1);students.add(s2);students.add(s3);

        students.add(s4);students.add(s5);students.add(s6);

        return students;

    }

    public static void main(String[] args) {
        //方法1,獲取成績小於等於指定分數,的全部學生
        System.out.println("-------------------------------");
        List<Student> scoredayu = STUDENTS.stream().filter(student -> student.getScore() <= 75).collect(Collectors.toList());
        scoredayu.stream().forEach(student -> System.out.println(student));
        System.out.println("-------------------------------");
//        //方法2,獲取指定班級,成績小於等於指定分數,的全部學生
        List<Student> collect2 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() <= 75).collect(Collectors.toList());
        collect2.stream().forEach(student -> System.out.println(student));
        System.out.println("-------------------------------");
//        //方法3,獲取指定班級,成績小於等於指定分數,的全部學生的姓名。注意返回類型
        List<String> collect3 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).map(student -> student.getName()).collect(Collectors.toList());
        collect3.stream().forEach(student -> System.out.println(student));
        System.out.println("-------------------------------");
//        //方法4,按成績由低到高排序,返回全部學生
        List<Student> collect4 = STUDENTS.stream().sorted(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore()-o2.getScore();
            }
        }).collect(Collectors.toList());
        collect4.stream().forEach(student -> System.out.println(student));
        System.out.println("-------------------------------");
//        //方法5,獲取指定班級,成績小於等於指定分數,成績由高到低排序,的全部學生
        List<Student> collect5 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).sorted(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getScore() - o1.getScore();
            }
        }).collect(Collectors.toList());
        collect5.stream().forEach(student -> System.out.println(student));
        System.out.println("-------------------------------");
//        //方法6,獲取指定班級,成績小於等於指定分數,成績由高到低排序,的全部學生的學號。注意返回類型
        List<Integer> collect6 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).sorted(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getScore() - o1.getScore();
            }
        }).map(student -> student.getNumber()).collect(Collectors.toList());
        collect6.stream().forEach(System.out::println);
        System.out.println("-------------------------------");
//        //方法7,獲取指定班級,成績小於等於指定分數,的全部學生
        List<Student> collect7 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).collect(Collectors.toList());
        collect7.stream().forEach(student -> System.out.println(student));
        System.out.println("-------------------------------");
    }
}

3 代碼優化

改動1

寫完了功能發現我的代碼在幹嘛,它再飄黃,有代碼潔癖的人看了肯定忍不了,來,看看怎麼優化,
在這裏插入圖片描述
看這個提示,什麼lambda可以被方法給替代,按照idea給的建議方案來改動
我們的打印代碼就變成了

collect7.forEach(System.out::println);

改動2

估計大家也能看到了飄黃的不止是這個地方,還有這個
在這裏插入圖片描述
雖然我英語不太好,但是憑藉着我的經驗我還是認出來了它的意思,
在這裏插入圖片描述
它的意思是比較器可以被lambda表達式給替代,那要是替代的話怎麼寫呢?直接alt+inter 看看idea給出的解決方案

        List<Student> collect5 = STUDENTS.stream().filter(student -> CLAZZ2.equals(student.getClazz()) && student.getScore() < 75).sorted((o1, o2) -> o2.getScore() - o1.getScore()).collect(Collectors.toList());

看到了 其實就是將 在這裏插入圖片描述
換成了在這裏插入圖片描述
在這裏插入圖片描述
這個改動之後,我總算是明白了爲什麼我之前看別人的例子,別人的例子總是那麼的簡潔,讓我有點些許的迷茫,不過現在知道這個結果怎麼來的之後,發現自己能看明白了這個操作。

4 Stream流API

Stream流的中間操作api有

api 操作解釋
limit 指定幾條數據
skip 跳過幾條數據從指定數據下標開始
distinct 去重
map 接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素。
sorted 排序
allMatch 檢查是否匹配所有元素
anyMatch 檢查是否至少匹配一個元素
noneMatch 檢查是否沒有匹配所有元素
findFirst 返回第一個元素
findAny 返回當前流中的任意元素
count 返回流中元素的總個數
max 返回流中最大值
min 返回流中最小值

關於其他的具體操作,我這裏就不在舉例子,如果業務中有需要要使用的話,建議大家先寫demo,還有,使用stream操作的時候,爲了防止後續人員看你的代碼懵逼,所以一定要在流上面寫註釋!!!,一定要在流上面寫註釋!!!一定要在流上面寫註釋!!!告訴別人你的這個操作目的是什麼!!!要不我就~~~~~~
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章