强大的Stream api----java8新特性,好用到怀疑人生

简介stream和stream api

stream是java8中处理集合的关键抽象概念,它可以指定你对集合进行的操作,可以进行非常复杂的查找、过滤和映射数据等操作。使用stream api 对集合数据进行操作,就类似于使用sql执行数据库 查询。也可以使用stream api来并行执行操作。简而言之,stream api 提供了一种高效且易于使用的处理数据的方式

它和stream(流)不是一个概念:什么是流?是数据渠道,用于操作数据源(集合或者数组)所生成的元素序列。 集合讲的是数据,流讲的是计算。
注意:
1.stream自己不会存储元素。
2.stream不会改变源对象。相反 他们会返回一个持有结果的新stream。
3.stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

stream操作的三个步骤

1.创建stream:通过数据源获取一个流 ;
2.中间操作:一个中间操作链,对数据源的数据进行处理;
3.终止操作:一个终止操作,执行中间操作链,并产生结果。

一、创建stream

创建方式代码中注释给了

public void test7(){
        //创建stream
        //1.可以通过Collection系列集合提供的stream()或parallelStream()
        List<String> list=new ArrayList<>();
        Stream<String> stream = list.stream();
        //2.可以通过Arrays中的静态方法stream()获取数组流
        People[] people=new People[10];
        Stream<People> stream1 = Arrays.stream(people);
        //3.通过stream类中的静态方法 of()
        //public static<T> Stream<T> of(T... values)
        Stream<String> stringStream = Stream.of("11", "22", "33");
        //4.创建无限流
        //(1)迭代
        //public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
        //seed 就相当于起始值,按照一元运算的规律产生一个无限流
        Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
        //(2)生成
        Stream<Double> generate = Stream.generate(() -> Math.random());

    }

二、中间操作

先定义一个集合:

 //中间操作
    List<People> peopleList = Arrays.asList(new People("黛玉",14,'女',1),
            new People("宝玉",16,'男',1),
            new People("宝钗",14,'女',1),
            new People("贾政",30,'男',1),
            new People("贾政",30,'男',2),
            new People("元春",18,'女',1)
    );

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!!而在终止操作时一次性全部处理,称为“惰性求值”。
注::中间操作不能产生结果,只有终止操作才能产生结果。

筛选和切片
filter: 接收lambda,从流中排除某些元素
limit: 截断流,使其元素不超过指定数量
skip(n): 跳过元素,返回一个扔掉了前n个元素的流,若流中的元素不足n个,则返回一个空的流
distinct: 筛选,通过流中的hashcode()和equals()去除重复元素

@Test
    public void test8(){
        //返回一个年龄大于15的新流
        Stream<People> peopleStream = peopleList.stream()
                .filter(a -> a.getAge() > 15);

        // 终止操作检验一下
        peopleStream.forEach(System.out::println);
    }

    @Test
    public void  test9(){
        //返回一个年龄大于15的流,只保留前两位
        Stream<People> limitStream = peopleList.stream()
                .filter(a -> a.getAge() > 15)
                .limit(2);
        //检验结果
        limitStream.forEach(System.out::println);
    }
    @Test
    public void test10(){
        //返回一个跳过前两个元素的新流
        Stream<People> skipStream = peopleList.stream()
                .filter(a -> a.getAge() > 15)
                .skip(2);
        //检验结果
        skipStream.forEach(System.out::println);
    }
    @Test
    public void test11(){
        //返回一个去除重复元素的流(这个使用的前提是:javaBean中重写了.equals()和.hashCode()这两个方法)
        Stream<People> distinctStream = peopleList.stream()
                .filter(a -> a.getAge() > 15)
                .distinct();
        //检验结果
        distinctStream.forEach(System.out::println);
    }

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

//映射  map/flatmap

    @Test
    public void test12(){
        List<String> list = Arrays.asList("aaa", "bbb", "ccc");
        //全部大写
        list.stream()
                .map(a->a.toUpperCase())
                .forEach(System.out::println);
        //找出年龄大于15 的所有年龄
        peopleList.stream()
                .map(People::getAge)
                .filter(a->a>15)
                .forEach(System.out::println);

        //map 与 flatmap之间的区别是
        Stream<Stream<Character>> streamStream = list.stream()
                .map(StreamApiTest::change);
        streamStream.forEach(a->{
            a.forEach(System.out::print);
        });//{ {a,a,a},{b,b,b},{c,c,c} }


        System.out.println("````````````````````````````````````````````````");

        Stream<Character> characterStream = list.stream()
                .flatMap(StreamApiTest::change);
        characterStream.forEach(System.out::print);//{ a,a,a,b,b,b,c,c,c }
    }

    //定义一个方法 把字符串转换成字节流
    public static Stream<Character> change(String string){
        List list=new ArrayList();

        for (char c : string.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

排序:
sorted():自然排序
sorted(comparator com):定制排序

//自然排序 定制排序
    @Test
    public void test13(){
        List<String> list = Arrays.asList("aaa", "ccc", "eee", "ddd", "bbb");

        list.stream()
                .sorted()
                .forEach(System.out::println);

        peopleList.stream()
                .sorted((a,b)->{
                    if (a.getAge()==b.getAge()){
                        return a.getName().compareTo(b.getName());
                    }else {
                        return Integer.compare(a.getAge(),b.getAge());
                    }
                })
                .forEach(System.out::println);
    }

三、终止操作

查找和匹配
allmatch:查找是否匹配所有元素
anymatch:检查是否至少匹配一个元素
nonematch:是否全部都不匹配
findfirst:返回第一个元素
findany:返回当前流中的任意元素
count:返回当前流中元素的总数
max:返回流中的最大值 min:返回流中的最小值

就懒了,这里就没敲代码了,直接就能点出来,会有提示。☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺

归约 :reduce 可以将流中的元素反复结合起来得到一个值

@Test
    public void test14(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        Integer sum = list.stream()
                .reduce(0, (a, b) -> a + b);
                //这里的意思是先把0赋值给a 1赋值给b  加的结果再赋值给a,2赋值给b   以此类推
        System.out.println(sum);
    }

收集:collect 将流转换成其他形式。接收一个collector接口的实现,用于给stream中元素做汇总的方法

@Test
    public void test15(){

        List<String> list = peopleList.stream()
                .map(People::getName)
                .collect(Collectors.toList());

        ArrayList<String> arrayList = peopleList.stream()
                .map(People::getName)
                .collect(Collectors.toCollection(ArrayList::new));


        Set<String> set = peopleList.stream()
                .map(People::getName)
                .collect(Collectors.toSet());

        HashSet<String> hashSet = peopleList.stream()
                .map(People::getName)
                .collect(Collectors.toCollection(HashSet::new));

        //总数
        peopleList.stream()
                .collect(Collectors.counting());

        //平均值
        peopleList.stream()
                .collect(Collectors.averagingDouble(People::getAge));

        //总和
        peopleList.stream()
                .collect(Collectors.summarizingDouble(People::getAge));

        //最大值
        Optional<People> maxAgePeople = peopleList.stream()
                .collect(Collectors.maxBy((a, b) -> Double.compare(a.getAge(), b.getAge())));

        //最小值
        Optional<Integer> minAge = peopleList.stream()
                .map(People::getAge)
                .collect(Collectors.minBy(Integer::compare));
        //多级分组---应该可以返回树图,就是不知道具体怎么写
        Map<Character, Map<String, List<People>>> collect = peopleList.stream()
                .collect(Collectors.groupingBy(People::getSex, Collectors.groupingBy(a -> {
                    if (a.getAge() > 15) {
                        return "测试";
                    } else {
                        return "测试1";
                    }
                })));
        System.out.println(collect);
    }

并行流(parallelStream)和顺序流:
并行流就是把一个内容分成多个数据块,并用不同的线程处理每个数据块的流。
顺序流的话感觉就是单线程操作的,并行流的话感觉就像是多线程操作。想清楚了解的话可以看一下fork/join框架。

@Test
    public void test16(){

        Instant start=Instant.now();
        long sum = 0L;
        for (long i=0;i<=100000000000L;i++){
            sum+=i;
        }
        Instant end=Instant.now();
        System.out.println("消耗的时间为:"+ Duration.between(start,end).toMillis());//消耗的时间为:44917

        System.out.println("==========================");
        Instant start1=Instant.now();
        LongStream.rangeClosed(0,100000000000L)
                .parallel()
                .reduce(0,Long::sum);
        Instant end1=Instant.now();
        System.out.println("消耗的时间为:"+ Duration.between(start1,end1).toMillis());//消耗的时间为:38589
    }

总结

这个写起来特别简单,代码量会少很多,毕竟是大佬封装好的,拿来直接用就可以了。
**注意:**项目中给不给使用还是问清楚比较好,毕竟不懂lambda的是看不懂你写的啥。维护起来可能会比较吃力。会被骂的。。。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值