美文网首页
Java8 stream

Java8 stream

作者: 黄二的NPE | 来源:发表于2018-06-04 09:19 被阅读7次
    • stream是什么?

    可以把Stream当成一个高级的Iterator(迭代器)。普通的Iterator,用户只能一个一个的遍历元素并对其执行某些操作;高级的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,stream将会开几个线程并行执行这些操作.

    • 举个栗子

    List<String> list = Arrays.asList("one","two","three", "four","five");
    list.stream().filter(str -> str.length() > 3).forEach(System.out::println);
    
    使用stream的一般过程

    Java stream的使用过程可以分为三个步骤

    1. 创建stream
    2. 转换stream(每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换))
    3. 汇聚操作(对Stream进行Reduce操作,获取想要的结果)
    • Java stream的使用过程

    创建stream
    1. 通过stream类的静态方法
    • Stream.of(创建一个定长的strea)
    Stream<String> stream = Stream.of("1","2","3");
    
    • Stream.generate(创建一个无限长的stream)
    Stream<Double> stream = Stream.generate(Math::random);
    
    • Stream.iterate(也是生成一个无限长的stream)
    Stream<Integer> stream = Stream.iterate(1, item -> item + 1);
    
    1. 通过 collection的 stream()方法
      Collection实现了stream()方法,它的子类(比如list,map)都拥有该方法.
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    

    使用:

    List list = new ArrayList(Arrays.asList("1", "2", "3"));
    Stream<String> stream = list.stream();
    
    转换stream
    1. distinct (对重复的流元素去重)
    List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
    list.stream().distinct().forEach(System.out::println);
    

    出来的结果是: 1,3,5,7,9 ; 1,3被去重了

    1. filter (过滤器:只返回符合要求的元素)
            List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
            list.stream().filter(i -> i > 4).forEach(System.out::println);
    

    在这个例子中, i <= 4 的元素都被剔除掉了,只打出 5,7,9三个元素

    1. map(原stream的元素经过计算转变成为另一个stream)
            List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
            list.stream().map(i -> i + 4).forEach(System.out::println);
    

    本来应该输出1,1,3,3,5,7,9 ; 但是经过i + 4之后,变成输出 4,4,7,7,9,11,13

    1. peek(peek方法方法会使用一个Consumer消费流中的元素,但是返回的流还是包含原来的流中的元素)
    List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
    list.stream().peek(System.out::println).map(i -> i + 4).count();
    

    peek方法返回void

    1. limit(限制返回多少个元素)
            List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
            list.stream().limit(2).forEach(System.out::println);
    

    本来应该输出全部元素的,但是实际上只输出2个元素

    1. skip(和limit是相对的操作,limit是保存前n个元素,skip是跳出前n个元素)
            List<Integer> list = new ArrayList(Arrays.asList(1,1,3,3,5,7,9));
            list.stream().skip(2).forEach(System.out::println);
    

    实际上输出3,3,5,7,9

    1. sorted(对元素进行排序)
     List<Integer> list = new ArrayList(Arrays.asList(1, 1, 11, 3, 3, 5, 7, 9));
     list.stream().sorted((x, y) -> y - x).forEach(System.out::println);
    

    倒序
    PS: 我们对stream进行N次转换, 以为一共执行了 N个循环,实际上只进行了一次循环

    汇聚操作

    汇聚操作(也称为折叠)接受一个元素序列为输入,反复使用某个合并操作,把序列中的元素合并成一个汇总的结果.。比如查找一个数字列表的总和或者最大值,或者把这些数字累积成一个List对象

    汇聚操作的分类

    1. 可变汇聚(把输入的元素们累积到一个可变的容器中,比如Collection或者StringBuilder)
    • 原生collect
      <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
      看一个栗子: 下面代码的作用是把猫的名字提取出来,放到一个新list里面
    List<Cat> cats = new ArrayList<>(Arrays.asList(new Cat("one", 21), new Cat("two", 22)));
    cats.stream().collect(ArrayList::new, (list, item) -> list.add(item.getName()), (list1, list2) -> list1.addAll(list2)).forEach(System.out::println);
    

    第一个函数生成一个新的ArrayList实例
    第二个函数接受两个参数,第一个是前面生成的ArrayList对象,二个是stream中包含的元素,函数体就是把stream中的元素加入ArrayList对象中。第二个函数被反复调用直到原stream的元素被消费完毕
    第三个函数也是接受两个参数,这两个都是ArrayList类型的,函数体就是把第二个ArrayList全部加入到第一个中(为什么会有第三步呢?因为第二步他可能是并行操作的,即第二步会产生多个list,第三步把第二步中产生的所有list都添加到新的一个list中)

    • Collectors(工具类)
      如果你感觉原生的collect很难用,你可以用collectors来实现.
            List<Cat> cats = new ArrayList<>(Arrays.asList(new Cat("one", 21), new Cat("two", 22)));
            cats.stream().map(cat -> cat.getName()).collect(Collectors.toList());
    
    1. 其它汇聚
    • count 计算stream中的元素的个数
    • allMatch 是不是stream中所有元素都满足给定的匹配条件
    • findFirst 查找stream的第一个元素
    List<Cat> cats = new ArrayList<>(Arrays.asList(new Cat("one", 21), new Cat("two", 22)));
    Optional<String> first = cats.stream().map(cat -> cat.getName()).findFirst();
    System.out.println(first.get());
    

    findFirst会返回一个optional对象,optional的用法后面再说

    • max 和 min

    相关文章

      网友评论

          本文标题:Java8 stream

          本文链接:https://www.haomeiwen.com/subject/tcrojftx.html