2020-07-04 java8新特性系统学习之Stream API

Stream 流的概念(自己的理解)

流就是用来操作数据源的。比如,工厂的流水线,数据源就是一些零件,然后工厂里面有流水线,流水线是做什么的呢?他会对这些零件进行加工,最后得到一个新的产品。对应过来Stream流就是对集合、数组等进行流水线式的操作,最后得到一个新的流,在这个流水线上,我们可以对这个流进行一些操作,比如筛选切片排序等。

Stream的操作三个步骤

1、创建一个流
一个数据源(集合、数组),获取到一个流
2、中间操作
一个中间操作链,对数据源的数据进行处理
3、终止操作(终端操作)
一个终止操作、执行中间操作链,并产生一个结果
在这里插入图片描述

一、创建流\获取流

先准备一个Emp的集合,下面会举例会使用到

 List<Emp> es = Arrays.asList(
            new Emp("zs", 30, 9999.99),
            new Emp("lqs", 39, 8888.88),
            new Emp("yjx", 29, 7777.77),
            new Emp("ddd", 36, 8888.88),
            new Emp("xxx", 20, 7777.77)
    );

1、可以通过Connection系列集合提供的stream()或者parallelStream()获取流

	List<String> list = new ArrayList<>();
    Stream<String> stream = list.stream();

2、通过Arrays中的静态方法stream()获取数组流

	int[] arr = new int[10];
    IntStream str = Arrays.stream(arr);

3、通过Stream类中的静态方法of()获取流

Stream<String> stream1 = Stream.of("aa", "bb", "cc");

1中的数据源是list,2中的数据源是arr,3中的数据源是"aa", “bb”, “cc”

4、创建无限流 ---- 迭代

	Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2);
    stream2.limit(10).forEach(System.out::println);

共产生10个数,从0开始,依次+2*

创建无限流 -----生成

	Stream.generate(() -> Math.random())
                .limit(5)
                .forEach(System.out::println);

二、中间操作

1、filter – 接受Lombda,从流中排出某些元素

	 @Test
    public void test1(){
        //中间操作
        Stream<Emp> stream = es.stream().filter(e -> e.getAge() > 30);
        //终止操作
        stream.forEach(System.out::println);
    }

输出结果
在这里插入图片描述

中间操作,不会执行任何操作,只有当终止操作执行以后,所有的中间操作和终止操作才全部执行,这个过程叫做惰性求值或延迟加载

2、limit – 截断流,使其元素不超过给定的数量

	@Test
    public void test2(){
        es.stream().filter(e -> e.getSalary() > 8000).limit(2).forEach(System.out::println);
    }

对Emp这个集合进行流操作,首先进行过滤,只选工资大于8000,然后得到的结果只选2个并打印

3、skip() – 跳过元素,返回一个扔掉前n个元素的流,若流中不足n个,则返回一个空流

	@Test
    public void test3(){
        es.stream().filter(e -> e.getSalary() > 5000).skip(4).forEach(System.out::println);
    }

对Emp集合进行流操作,先是过滤,取出薪资大于5000的,然后跳过前4个,并打印后面的,如果过滤后的流中的元素不足4个,那你把前4个跳过了,肯定流中就没有元素了,就返回空

执行结果:本来有5个,跳过前4个,就只打印最后一个
在这里插入图片描述
4、distinct – 筛选,通过流所生成元素的hashcode()和equals()去除重复元素
我们在Emp集合中复制几个emp,测试一下去重

List<Emp> es = Arrays.asList(
            new Emp("zs", 30, 9999.99),
            new Emp("lqs", 39, 8888.88),
            new Emp("yjx", 29, 7777.77),
            new Emp("ddd", 36, 8888.88),
            //下面是3条重复数据
            new Emp("xxx", 20, 7777.77),
            new Emp("xxx", 20, 7777.77),
            new Emp("xxx", 20, 7777.77)
    );
	@Test
    public void test4(){
        es.stream().filter(e -> e.getSalary() > 5000).skip(4).distinct().forEach(System.out::println);
    }

输出结果
在这里插入图片描述
可以发现我们写了distinct()的,但是并没有去重,那是因为distinct()是通过hashcode()和equals()去除重复元素的,所以我们需要在Emp实体类中重写hashcode()和equals()这两个方法
再次运行就好了

Map映射(也属于中间操作,重点理解)

map- 接收Lambda ,将元素转换成其他形式或提取信息。接收一 个函数作为参数,该函数会被应用到每个元素上,并将其映射成- -个新的元素。flatMap- 接收- - 一个函数作为参数,将流中的每个值都换成另-个流,然后把所有流连接成一-个流

上面听起来可能有点抽象,举例说明更容易理解

 	@Test
    public void test5(){
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd", "ee");
        list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);
    }

打印结果就是将list所有元素全部转换为大写

介绍映射说接收一 个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素,所以意思就是他从数据源中的"aa"提取出来应用到map这个函数上,又取出一个"bb"应用到map函数上,把每个元素都应用到map这个函数上,最后产生一个新流,得到一个结果

再举个例子,我们要提取Emp集合中每个Emp的名字

	@Test
    public void test6(){
        es.stream().map(Emp::getName).forEach(System.out::println);
    }

这样就是将es这个集合中的每个Emp都应用到map函数上,使用方法引用获取名字,最后得到一个结果

排序

sorted( )一自然排序

	@Test
    public void test7(){
        List<String> list = Arrays.asList("bb", "aa", "cc", "dd", "ee");
        list.stream().sorted().forEach(System.out::println);
    }

最后打印结果为aa,bb,cc,dd,ee

sorted(Comparator com)- -定制排序

	@Test
    public void test8(){
        es.stream().sorted((o1,o2) -> {
            if (o1.getName().equals(o2.getName())){
                //如果姓名一样就按年龄排
                return o1.getAge().compareTo(o2.getAge());
            }else {
                //否则按姓名排
                return o1.getName().compareTo(o2.getName());
            }
        }).forEach(System.out::println);
    }

输出结果
在这里插入图片描述

三、终止操作

1、allMatch-检查是否匹配所有元素

	@Test
    public void test1(){
        boolean match = es.stream().allMatch(emp -> emp.getAge().equals(20L));
        System.out.println(match);
    }

输出结果为false,意思就是说es这个集合里面是不是所有都匹配年龄等于20,肯定不是啊,我还有36岁,39岁这些呢

2、anyMatch-检查是否至少匹配一个元素

	@Test
    public void test2(){
        boolean match1 = es.stream().anyMatch(emp -> emp.getName().equals("ddd"));
        System.out.println(match1);
    }

输出结果为true,意思就是es这个集合里面是不是至少有一个姓名是ddd的,只要有就返回true

3、noneMatch-检查 是否没有匹配所有元素

	@Test
    public void test3(){
        boolean match1 = es.stream().noneMatch(emp -> emp.getName().equals("ddd"));
        System.out.println(match1);
    }

输出结果为false,就是说es这个集合里面是不是没有姓名叫ddd的,但是匹配到了,所以返回false

4、findFirst-返 回第一个元素

	@Test
    public void test4(){
        Optional<Emp> op = es.stream().sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary())).findFirst();
        System.out.println(op.get());
    }

意思就是对es这个集合里面的元素的薪资进行一个排序,然后获取第一个元素,这里是获取薪资最高的那个,需要注意的是,他返回的是一个Optional,可以通过get()方法获取Optional中封装的对象

为什么需要这个Optional呢?

因为java8尽可能地区避免空指针异常,怎么避免呢?他就设计了一个Optional这样的容器类,把有可能为空的对象封装到这个容器里,那么他就有一些方法可以使用,比如orElse,作用就是,Optional中封装的那个对象为空,你就可以放个替代的对象,这样就避免了空指针异常

5、findAny返回当 前流中的任意元素
需求:现在我有三个姓名为xxx的程序员,我要随便找个加入到开发团队中

	@Test
    public void test5(){
        Optional<Emp> op = es.parallelStream().filter(e -> e.getName().equals("xxx")).findAny();
        System.out.println(op.get());
    }

这里使用的是并行流,可以理解为多个线程同时找,谁先找到就把那个程序员加入到开发团队中,如果使用串行流,他是一个一个找,找到一个就取出来

6、count-返 回流中元素的总个数

	@Test
    public void test6(){
        System.out.println(es.stream().count());
    }

输出结果为7,就是es集合里面有多少个元素,当然你可以过滤等多个操作

7、max-返回流中最大值

	@Test
    public void test7(){
        Optional<Emp> op = es.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(op.get());
    }

按照薪资排序找出薪资最大的那个元素

8、min-返回流中最小值
需求:获取公司中薪资最小的薪资是多少

	@Test
    public void test8(){
        Optional<Double> op = es.stream().map(Emp::getSalary).min(Double::compare);
        System.out.println(op.get());
    }

输出结果为7777,数据源是es这个集合嘛。先把每个元素应用到map函数上,生成一个新的元素就是每个元素的薪资,然后获取这个流中的元素的最小值,放到Optional容器中,最后获取Optional中的值

对于Stream API我了解的不是很深,之后有遇到新的知识点,我也会记录下来,stream流的知识点还有很多,下篇继续学习

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值