Stream流使用及性能

目录

一    什么是Stream流

二    Stream流的区别

三    关注单独部分

四    关注整体部分

五    Stream流两大类

六    中间操作 

七    终结操作

八    Stream流的使用

九    Stream性能

十     使用建议


一    什么是Stream流

        stream流操作是Java 8提供一个重要新特性,它允许开发人员以声明性方式处理集合,其核心类库主要改进了对集合类的 API和新增Stream操作。Stream类中每一个方法都对应集合上的一种操作。将真正的函数式编程引入到Java中,能 让代码更加简洁,极大地简化了集合的处理操作,提高了开发的效率和生产力。

二    Stream流的区别

        stream流是抽象的,并且它关注的是整体的情况,而不是某个单独的部分,所以当你构建一个程序的时候,有时候你的只是写了一堆,逻辑上如果这个这么做,如果那个不这么做,或者使用Switch语句啊,创建一个集合等等,这么做就是在关注单独的部分,但是stream专注于整体的画面,而并非单独的部分,下面我用两段代码来带你们理解下这里的意思。

public class Student {
    //姓名
    private String name;

    //年龄
    private Long age;

    //性别
    private String sex;

    public String getName() {
        return name;
    }

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

    public Long getAge() {
        return age;
    }

    public void setAge(Long age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

在上面我们创建了一个学生类,并且赋予了它三个属性,分别是姓名,年龄,性别。

三    关注单独部分

public static void main(String[] args) {
        //添加学生信息
        List <Student> list = new ArrayList<>();
        list.add(new Student("鸡哥",20L,"女"));
        list.add(new Student("坤哥",21L,"男"));
        list.add(new Student("蔡哥",22L,"女"));
        list.add(new Student("徐哥",23L,"男"));

        //只查找一位学生中年龄大于22的(单独部分)
        //用于装载年龄大于22的学生
        List <Student> specialStu = new ArrayList<>();
        int limit = 1;
        int counter = 0;
        for (Student stulist : list){
            if (stulist.getAge() > 22){
                specialStu.add(stulist);
                counter ++;
                if (counter == limit){
                    break;
                }
            }
        }
        specialStu.forEach(System.out::println);
    }

        在这段代码中,我们设置了个学生类型的集合,然后对该集合添加数据,在后面的语句我们又新建了一个specialStu用于装载年龄大于22的学生。

        接下来看下面的循环部分,我们有Limit(限制器)限制我们只查询一条数据,Counter(计数器)每执行一次循环加一,在此处这个for循环里我们循环了全部学生信息,并在此筛选年龄大于22的学生信息,如果查询到有学生信息大于22,我们的计数器会加一,紧接着判断计数器是否与我们的限制条件相等,如果相等则打破整个循环,最后打印那位年龄大于22的学生信息,下面是控制台的信息。

⚪输出结果 

student{name='徐哥',age=23,sex='男'}

        可以看到,在这一段代码中我们更加注重在单个部分,也就是筛选出一个年纪为22的学生的信息,接下来我们在看看另一段代码。

四    关注整体部分

public class Test2 {
    public static void main(String[] args) {
        //添加学生信息
        List<Student> list = new ArrayList<>();
        list.add(new Student("鸡哥",20L,"女"));
        list.add(new Student("坤哥",21L,"男"));
        list.add(new Student("蔡哥",22L,"女"));
        list.add(new Student("徐哥",23L,"男"));

        List<Student> specialStu = list.stream()
                .filter(stu -> stu.getAge() > 22)
                .limit(1)
                .collect(Collectors.toList());
        specialStu.forEach(System.out::println);
    }
}

⚪输出结果 

student{name='徐哥',age=23,sex='男'}

        上面的代码也是同样的输出结果,但是整体上效率更为高效也更为整洁,且整个流程执行下来是一个整体,并非像我们一开始的逻辑,把需要的数据筛选出来并传入最终的集合里,看起来十分的冗余,到这里我们的任务就已经完成了,可能目前你并不清楚它是怎么实现的,但是你不必担心,接下来我会为你解答如何使用Stream流。

五    Stream流两大类

在学会使用stream流之前我们先要知道
官方将stream流分为了两大类:终结操作(Terminaloperations)和中间操作(Intermediate operations)。

 

        中间操作会返回一个新的流,一个流可以后面跟随零个或多个中间操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后会返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。而是在终结操作开始的时候才真正开始执行。

         终结操作是指返回最终的结果。一个流只能有一个终结操作,当这个操作执行后,这个流就被使用“光”了,无法再被操作。所以这必定这个流的最后一个操作。只有终结操作执行的时候,才会真正开始流的遍历,并且会生成一个结果。

六    中间操作 

        上图为中间操作所包含的部分方法,接下来回到之前的代码,在之前的代码中,我们使用了Filterlimit,这几种方法在我们的Stream流中都叫做中间操作,且有两个中间操作,每当我们使用了一次中间操作我们就会返回一个新的流交给后面的中间操作去处理。

七    终结操作

        终结操作一般用于返回最终的结果,且一个流只能拥有一个终结操作,当这个终结操作执行后,这个流就被使用完了,无法继续操作。所以这必须是整个流的最后操作,只有当终结操作执行时才会开始真正的遍历,然后生成一个结果。

 

八    Stream流的使用

聊完Stream流的中间操作跟终结操作后接下来就该告诉大家Stream流的使用了。

8.1.Filter方法(过滤器:过滤出满足条件的元素)

在下面这段代码中,我们需要查找全部性别为女的学生的信息。

public static void main(String[] args) {
        //添加学生信息
        List<Student> list = new ArrayList<>();
        list.add(new Student("鸡哥",20L,"女"));
        list.add(new Student("坤哥",21L,"男"));
        list.add(new Student("蔡哥",22L,"女"));
        list.add(new Student("徐哥",23L,"男"));

        //过滤出全部性别为女的学生信息
        Stream<Student> specialStu = list.stream()
                        .filter(stu -> stu.getSex().equals("女"));
        specialStu.forEach(System.out::println);
    }

⚪输出结果

student{name='鸡哥',age=20,sex='女'}
student{name='蔡哥',age=22,sex='女'}

8.2.Limit方法(限制器:获取*个元素)

在下面这段代码中,我们需要获取前三名学生的信息。

 public static void main(String[] args) {
        //添加学生信息
        List<Student> list = new ArrayList<>();
        list.add(new Student("鸡哥",20L,"女"));
        list.add(new Student("坤哥",21L,"男"));
        list.add(new Student("蔡哥",22L,"女"));
        list.add(new Student("徐哥",23L,"男"));

        //取前三名学生的信息
        Stream<Student> specialStu = list.stream()
                        .limit(3);
        specialStu.forEach(System.out::println);
    }

⚪输出结果

student{name='鸡哥',age=20,sex='女'}
student{name='坤哥',age=21,sex='男'}
student{name='蔡哥',age=22,sex='女'}

8.3.Count(计数器:用于计算集合的长度)

在下面这段代码中,我们需要查询出全部学生的个数。

 public static void main(String[] args) {
        //添加学生信息
        List<Student> list = new ArrayList<>();
        list.add(new Student("鸡哥",20L,"女"));
        list.add(new Student("坤哥",21L,"男"));
        list.add(new Student("蔡哥",22L,"女"));
        list.add(new Student("徐哥",23L,"男"));

        //取全部学生的数量
        Long num = list.stream()
                        .count();
        System.out.println("学生的个数为" + num);
    }

 ⚪输出结果

学生的个数为4

8.4.Distinc(去重:用于去除集合里重复的元素)

在下面这段代码中,我们需要去除集合里重复的元素。

 public static void main(String[] args) {
        List <String> str = new ArrayList<>();
        str.add(0,"h");
        str.add(1,"e");
        str.add(2,"l");
        str.add(3,"l");
        str.add(4,"o");

        //去除集合重复的元素,并使用终结操作将其转化为List类型 
        List <String> distinct = str.stream()
                .distinct()
                .collect(Collectors.toList());

        distinct.forEach(System.out::print);
    }

 ⚪输出结果

helo

8.5.Sorted(排序:对数组里面的内容进行排序)

在下面这段代码中,我们要对集合进行排序。

public static void main(String[] args) {
        List <Integer> str = new ArrayList<>();
        str.add(0,1);
        str.add(1,3);
        str.add(2,5);
        str.add(3,4);
        str.add(4,2);

        //对打乱的集合进行排序(从小到大),并使用终结操作将其转化为List集合
        List <Integer> distinct = str.stream()
                .sorted()
                .collect(Collectors.toList());

        distinct.forEach(System.out::print);
    }

⚪输出结果

12345

8.6.Firstfind(查询第一个:查询出集合里第一个满足条件的元素)

在下面这段代码中,我们需要查询出第一个姓名为”蔡哥“的学生信息

public static void main(String[] args) {
        //添加学生信息
        List<Student> list = new ArrayList<>();
        list.add(new Student("鸡哥",20L,"女"));
        list.add(new Student("坤哥",21L,"男"));
        list.add(new Student("蔡哥",22L,"女"));
        list.add(new Student("徐哥",23L,"男"));
        list.add(new Student("蔡哥",24L,"女"));

        //查询出集合里第一个姓名为”蔡哥“的学生的信息
        Optional<Student> first = list.stream()
                .filter(stu -> stu.getName().equals("蔡哥"))
                .findFirst();

        System.out.println(first);
    }

⚪输出结果

Optional[student{name='蔡哥',age=22,sex='女'}]

8.7.Map(映射:针对流中的每一个数据元素进行转换操作)

在下面这段代码中,我们需要将String类型的数组转化为Int类型的数组

 public static void main(String[] args) {
        //添加学生信息
        List <String> str = new ArrayList<>();
        str.add(0,"1");
        str.add(1,"2");
        str.add(2,"3");
        str.add(3,"4");

        //将String类型的集合转化为int类型,并使用终结操作返回List集合
        List <Integer> in = str.stream()
                        .map(info -> {
                            return Integer.parseInt(info);
                        }).collect(Collectors.toList());

        in.forEach(System.out::println);
    }

⚪输出结果

1234

九    Stream性能

        Stream流的处理速度是不如传统的Iterator(迭代器)处理速度快的,但是实际上在做业务的时候这些运行时间差都是可以忽略不计的,,恰恰相反Stream流可以使你的代码可读性及简洁度更高。

9.1Stream和迭代器的区别

        Stream 可以并行化操作,迭代器只能命令式地、串行化操作。也就是当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream 的并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程,下面用一张图来给你们解释下为什么Stream在并行时效率更高。

Iterator(迭代器)

迭代器在遍历时是读完当前元素后才会读取下一个元素。

 Stream(流)

        Stream流在并行的时候会将元素拆分成为多段来进行遍历,每个都在不同的线程中进行遍历,最后会将结果一起输出,相同的遍历在Stream并行的时候效率会高很多。

十     使用建议

        当数据量不大或者没有太耗时的操作时,顺序执行(如iterator)往往比并行执行更快。当任务涉及到耗时操作(如I/O)并且任务之间不互相依赖时,那么并行化就是一个不错的选择。通常而言,将这类程序并行化之后,执行速度会提升好几个等级;

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
stream是在处理数据时非常常见的一种方式。重复使用stream可以带来很多好处,包括提高性能和减少资源消耗。 首先,重复使用stream可以避免不必要的内存分配和释放开销。创建和销毁stream对象需要一定的时间和资源。如果在处理数据时频繁地创建和销毁对象,将会增加系统的负担。而重复使用已经创建的stream对象,可以减少这种开销,并且提高处理数据的效率。 其次,重复使用stream可以减少对文件或网络资源的频繁访问。在处理大型文件或网络请求时,频繁地打开和关闭对象会增加I/O操作的开销。通过重复使用已经打开的stream对象,可以避免这种开销,提高数据读取或写入的速度。 另外,重复使用stream还可以简化代码逻辑。在多次读写数据的场景中,如果每次都要重新创建和配置对象,会导致代码冗余和可读性下降。通过重复使用已经存在的stream对象,可以简化代码,使其更加清晰和易于维护。 需要注意的是,在重复使用stream时,要确保正确地管理的状态和位置。例如,在读取文件时,需要在每次使用前将的位置重置到起始位置,以便从头开始读取数据。 综上所述,重复使用stream可以提高性能、减少资源消耗,并简化代码逻辑。在处理数据时,可以考虑使用这种方式来优化程序的效率和可维护性。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值