还看不懂同事用的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操作的时候,为了防止后续人员看你的代码懵逼,所以一定要在流上面写注释!!!,一定要在流上面写注释!!!一定要在流上面写注释!!!告诉别人你的这个操作目的是什么!!!要不我就~~~~~~
在这里插入图片描述

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