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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值