zoukankan      html  css  js  c++  java
  • java8 Stream API笔记

    生成Stream Source的方式

    从Collection和数组生成

    * Collection.stream()
    * Collection.parallelStream()
    * Arrays.stream(T array) or Stream.of()
    

    从BufferedReader

    * java.io.BufferedReader.lines();
    

    静态工厂

    * java.util.stream.IntStream.range();
    * java.nio.file.Files.walk();
    

    使用Spliterator

    * java.util.Spliterator
    

    其他

    * Random.ints();
    * BitSet.stream();
    * Pattern.splitAsStream(java.lang.CharSequence);
    * JarFile.stream();
    

    流的操作

    * Intermediate:一个流后面跟随零个或多个intermediate操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,
    交给下一个操作使用。这类操作都是以惰性(lazy)化的,就是说,就是
    说,仅仅调用到这类方法,并没有真正开始流的遍历。多个intermediate操作会在Terminal操作的时候融合起来,一次循环完成。Stream你有个操作函数的集合,每次转换操作就把转换函数放入这个集合中,在Terminal操作的时候循环Stream对应的集合,然后对每个元素执行所有的函数
    * Terminal:一个流只能有一个terminal操作,当这个操作执行后,流就无法再操作了。也就是说Terminal操作是流的最后一个操作。Terminal操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个side effect
    * short-circuiting。用以指:
    

    对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。
    对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。
    当操作一个无限大的 Stream,而又希望在有限时间内完成操作,则在管道内拥有一个 short-circuiting 操作是必要非充分条件。

    一个流操作的实例:

    int sum = widgets.stream()//获取source
              .filter(w->w.getColor() == RED)//filter 进行数据筛选
              .mapToint(w->w.getWeight())//mapToint进行数据转换
              .sum();

    stream()获取当前小物件的source,filter和mapToInt为intermediate操作,进行数据筛选和转换,最后一个sum操作为terminal操作,对符合条件的小物件作重量求和

    流的操作

    • Intermediate:
      map(mapToint、flatMap)、filter、distinct、sort、peek、limit、skip、parallel、sequential、unordered
    • Terminal
      forEach 、forEachOrder、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator
    • Short-circuiting:
      anyMatch、allMatch、noneMatch、findFirst、findAny、limit

    map/flatMap

    作用:把InputStream的每一个元素映射成output stream的另一个元素

    List output = wordList.stream();
    map(String::toUpperCase)
    collect(Collector.toList())

    例子:

    转换大小写
    List<String> output = wordList.stream().map(String::toUpperCase).collect(Collectors.toList());
    平方数
    List<Integer> nums = Arrays.asList(1,2,3,4);
    List<Integer> squareNums  = nums.stream().map(n-> n*n).collect(Collectors.toList());

    从上面的例子可以看出,map生成的是个1:1的映射,每个输入的元素都会按照规则转换成为另外一个元素。还有一些场景,是一对多映射关系的,这时需要flatMap

    
    Stream<List<Intege>> inputStream = Stream.of(Arrays.asList(1),
    Arrays.asList(2,3),Arrays.asList(4,5,6));
    Stream<Integer> outputStream = inputStream.flatMap((childList)->childList.stream));

    flatMap把input Stream 中的层级结构扁平化,就是讲最低层的元素抽出来放到一起,最终output的新stream里已经没有List了,都是Integer

    filter

    作用:

    filter 对原始Stream进行某项测试,通过测试的元素被留下来形成一个新的Stream

    例子:

    选出偶数

    Integer [] sixNums = {1,2,3,4,5,6};
    Integer [] evens = Stream.of(sixNums).filter(n->n%2== 0).toArray(Integer[]::new);

    forEach

    作用:

    forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。
    forEach 是 terminal 操作,因此它执行后,Stream 的元素就被“消费”掉了,你无法对一个 Stream 进行两次 terminal 运算。

    例子

    package forEach;
    
    import java.util.ArrayList;
    import java.util.stream.Stream;
    
    class Person{
        private String name;
        private String gender;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getGender() {
            return gender;
        }
        public void setGender(String gender) {
            this.gender = gender;
        }
        public Person(String name, String gender) {
            super();
            this.name = name;
            this.gender = gender;
        }
    
    }
    public class forEach {
        public static void main(String[] args) {
            ArrayList<Person> roster =new ArrayList<>();
            roster.add(new Person("liu","male"));
            roster.add(new Person("jiang","female"));
            roster.add(new Person("xiao","female"));
            roster.stream().filter(person->((Person) person).getGender().equals("female")).forEach(p->System.out.println(p.getName()));
        }
    }
    

    peek

    作用

    与forEach一样,但是peek是非terminal的操作。

    例子

    package forEach;
    
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class peekTest {
        public static void main(String[] args) {
            Stream.of("one","two","three","four")
                .filter(e->e.length()>3).peek(e->System.out.println("Filtered value:"+e))
                .map(String::toUpperCase).peek(e->System.out.println("Mapped value:"+e))
                .collect(Collectors.toList());
        }
    }

    findFirst

    作用

    返回stream中的第一个元素或者空。
    返回值类型是Optional。Optional是一个容器,可能含有值,也可能不包含。使用Optional的目的是尽可能避免NullPointerException

    例子

    package findAnyORfindFirst;
    
    import java.util.stream.Stream;
    
    public class findAnyORfindFirst {
        public static void main(String[] args) {
            String[] strArr= {"A","B","C"};
            Stream.of(strArr).findAny().ifPresent(System.out::println);
            Stream.of(strArr).findFirst().ifPresent(System.out::println);
        }
    }

    reduce

    作用

    把Stream元素组合起来。它提供一个起始值(种子),然后按照运算规则(BinaryOperator),和前面Stream的第一个、第二个、第三个、第n个元素组合。从这个意义上说,字符串拼接、数值的sum、min、max、average都是特殊的reduce.

    例子

    //字符串连接
    String concat = Stream.of("A","B","C","D").reduce("",String::concat);

    reduce()的第一参数为起始值,第二个人参数为BinaryOperator。这类有起始值的reduce()都返回具体的对象。但是如果没有给reduce()指定起始值,由于可能没有足够的元素导致不能生成对象,这时返回的是Optional。

    limit/skip

    作用

    limit返回Stream的前面n个元素
    skip跳过前n个元素

    例子

    package limitORskip;
    
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class LimitORskipDemo {
        public static void main(String[] args) {
            Integer [] nums= {1,2,3,4,5,6,7,8,9,10};
            List<Integer> list=Stream.of(nums).limit(5).skip(3).collect(Collectors.toList());
            list.forEach(System.out::println);
        }
    }

    sorted

    作用

    对集合排序

    例子

    package sorted;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class SortedTest {
        public static void main(String[] args) {
            Integer [] nums= {1,2,3,4,5};
            List<Integer> list=Stream.of(nums).sorted((a,b)->a.compareTo(b)).collect(Collectors.toList());
            list.forEach(System.out::println);
        }
    }
    

    max/min/distinct

    作用

    max 找最大值
    min 找最小值
    distinct 去重

    例子

    package MaxMinDistinct;
    
    import java.util.stream.Stream;
    
    public class MaxMinDistinct {
        public static void main(String[] args) {
            Integer[] nums= {5,3,5,3,4,6,7,8,6,8};
            Stream.of(nums).distinct().max((a,b)->a.compareTo(b)).ifPresent(System.out::println);;
            Stream.of(nums).distinct().min((a,b)->a.compareTo(b)).ifPresent(System.out::println);;
        }
    }

    Match

    作用

    Stream 中有三个match方法
    * allMatch:Stream中所有元素符合传入的 predicate,返回true
    * anyMatch:Stream中只要有一个元素符合传入的 predicate,返回true
    * noneMatch:Stream中没有一个元素符合传入的predicate,返回true

     package Match;
    
    import java.util.stream.Stream;
    
    public class MatchDemo {
        public static void main(String[] args) {
            Integer[] nums1= {1,3,5,-5,2,10};
            boolean hasNegtive=Stream.of(nums1).anyMatch(x->x<0);
            System.out.println("有负数:"+hasNegtive);
            Integer[] nums2= {1,3,5,5,2,10};
            boolean a=Stream.of(nums2).allMatch(x->x>0);
            System.out.println("全是正数:"+a);
            Integer[] nums3= {-1,-3,-5,-5,-2,-10};
            boolean none=Stream.of(nums2).noneMatch(x->x>0);
            System.out.println("没有正数:"+a);
        }
    }

    generate

    作用

    通过实现Supplier接口,然后把 Supplier 实例传递给 Stream.generate() ,你可以自己来控制流的生成。

    例子

    package generate;
    
    import java.util.stream.IntStream;
    
    public class GenerateDemo {
        public static void main(String[] args) {
            IntStream.generate(()->(int)(Math.random()*10)).limit(20).forEach(System.out::println);
        }
    }
    

    iterate

    作用

    第一个参数是起始值(seed),第二个参数是一元操作符函数(UnaryOperator)。
    如果seed是第一个元素,那么第二个就是f(seed),第三个就是f(f(seed))….以此类推

    例子

    package generate;
    
    import java.util.stream.Stream;
    
    public class Iterate {
        public static void main(String[] args) {
            Stream.iterate(0,x->x+3).limit(15).forEach(System.out::println);
        }
    }
    
  • 相关阅读:
    统计候选人
    九宫格输入法
    前端同学面试准备
    1、单元格内换行诀窍、合并单元格、身份证、日期乱码
    读写锁
    混合锁、互斥锁
    原子操作、自旋锁
    pipeline httpmodule
    vm +cenos7+gitlab 02
    vm +cenos7+gitlab 01
  • 原文地址:https://www.cnblogs.com/infoflow/p/7535853.html
Copyright © 2011-2022 走看看