zoukankan      html  css  js  c++  java
  • StreamAPI

    一、简介 

    Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作 。

    Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。

    同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。

    通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

    (Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。)

    常见Stream Source生成方式

    数据和集合获取

    1)Collection.stream()

    2)Collection.parallelStream()

    3)Arrays.stream(T array) or Stream.of()

    BufferedReader获取

    java.io.BufferedReader.lines()

    Stream常用操作

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

    Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

    Intermediate:

    map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

    Terminal:

    forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

    二、Stream使用样例

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.Stack;
    import java.util.stream.Collector;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
    import java.util.stream.Stream;
    import org.junit.Test;
    import org.mockito.internal.matchers.CompareTo;
     
    public class StreamTest {
     
        /**
         * 构造流的几种常见方法
         */
        @Test
        public void createStream() {
     
            // 通过数组获取Stream
            String[] strs = new String[] { "a", "b", "c" };
            Stream<String> s1 = Stream.of(strs);
            Stream<String> s2 = Arrays.stream(strs);
            Stream<String> s3 = Stream.of("a", "b", "c");
            // 通过集合
            List<String> strLists = Arrays.asList("a", "b", "c");
            Stream<String> s4 = strLists.stream();
     
            // 需要注意的是,对于基本数值型,目前有三种对应的包装类型 Stream:
            // IntStream、LongStream、DoubleStream。当然我们也可以用 Stream<Integer>、Stream<Long>
            // >、Stream<Double>,
            // 但是 boxing 和 unboxing 会很耗时,所以特别为这三种基本数值型提供了对应的 Stream。
            IntStream.of(new int[] { 1, 2, 3 }).forEach(System.out::println);
            IntStream.range(1, 3).forEach(System.out::println);
            IntStream.rangeClosed(1, 3).forEach(System.out::println);
        }
     
        /**
         * 流转换为其它数据结构
         */
        @Test
        public void streamToOther() {
            // 转换成Array
            Stream<String> s1 = Stream.of("a", "b", "c");
            String[] strArray = s1.toArray(String[]::new);
            // 转换成Collection
            Stream<String> s2 = Stream.of("a", "b", "c");
            List<String> list1 = s2.collect(Collectors.toList());
            Stream<String> s3 = Stream.of("a", "b", "c");
            List<String> list2 = s3.collect(Collectors.toCollection(ArrayList<String>::new));
            Stream<String> s4 = Stream.of("a", "b", "c", "c");
            Set<String> set1 = s4.collect(Collectors.toSet());
            Stream<String> s5 = Stream.of("a", "b", "c");
            Stack stack1 = s5.collect(Collectors.toCollection(Stack::new));
            // 转换成String
            Stream<String> s6 = Stream.of("a", "b", "c");
            String str = s6.collect(Collectors.joining()).toString();
        }
     
        /**
         * Stream常用操作
         */
        @Test
        public void streamOperate() {
     
            // map 转换大写
            Arrays.asList("lucy", "mark", "zhangsan").stream().map(String::toUpperCase)
            .forEach(w -> System.out.println(w));
            // map 求平方
            Arrays.asList(1, 2, 5, 9).stream().map(n -> n * n).forEach(w -> System.out.println(w));
     
            // flatMap 把 input Stream 中的层级结构扁平化.map是1对1,当有1对多的时候可以用flatMap转换成1对1
            // 下面最终的stream 中只有数字了,flatMap把List打散
            Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9))
            .flatMap(s -> s.stream()).forEach(System.out::print);
     
            // filter 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。
            // 过滤小于等于3的数据
            Stream.of(1, 2, 3, 4, 5, 6).filter(n -> n > 3).forEach(System.out::print);
     
            // forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式
            // forEach 是 terminal 操作.即执行该Stream就被消费掉了,不可以再使用
            Stream.of(1, 2, 3, 4, 5, 6).forEach(System.out::print);
             
            // peek 对每个元素执行操作并返回一个新的 Stream
            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 的第一个元素
            Stream.of(1, 2, 3, 4, 5, 6).findFirst().ifPresent(System.out::println);
             
            //这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则,
            //和前面 Stream 的第一个、第二个、第 n 个元素组合。
            //从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce
            //也有没有起始值的情况,这时会把 Stream 的前面两个元素组合起来,返回的是 Optional。
            //求和(有初始值)
            System.out.println(Stream.of(1, 2, 3, 4, 5, 6).reduce(0,(a,b) -> a+b));
            //求和(无初始值)
            System.out.println(Stream.of(1, 2, 3, 4, 5, 6).reduce(Integer::sum).get());
            //拼接字符串
            System.out.println(Stream.of("a","b","c").reduce("",String::concat));
            // 求最小值,minValue = -3.0
            System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min));
             
            //limit/skip limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素
            Stream.of(1, 2, 3, 4, 5, 6).limit(3).forEach(System.out::println);
            Stream.of(1, 2, 3, 4, 5, 6).skip(3).forEach(System.out::println);
             
            //sorted:对 Stream 的排序通过 sorted 进行,它比数组的排序更强之处在于你可以首先对 Stream 
            //进行各类 map、filter、limit、skip 
            //甚至 distinct 来减少元素数量后,再排序,这能帮助程序明显缩短执行时间。
            //根据字符串长度排序
            Stream.of("one", "two", "three", "four").sorted((w1,w2) -> w1.length()-w2.length())
            .forEach(System.out::println);
             
            //Match
            //allMatch:Stream 中全部元素符合传入的 predicate,返回 true
            //anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
            //noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
            //它们都不是要遍历全部元素才能返回结果。例如 allMatch 只要一个元素不满足条件,
            //就 skip 剩下的所有元素,返回 false。
            //判断数组里是否有大于9的数据
            System.out.println(Stream.of(1, 2, 3, 4, 5, 6).allMatch(n -> n>9));
             
             
            //java.util.stream.Collectors 类的主要作用就是辅助进行各类有用的 reduction 操作,
            //例如转变输出为 Collection,把 Stream 元素进行归组。
            class Person{
                public Person(String name,int age) {
                    this.name = name;
                    this.age = age;
                }
                private String name;
                private int age;
                public String getName() {
                    return name;
                }
     
                public void setName(String name) {
                    this.name = name;
                }
     
                public int getAge() {
                    return age;
                }
     
                public void setAge(int age) {
                    this.age = age;
                }
     
                @Override
                public String toString() {
                    return "Person [name=" + name + ", age=" + age + "]";
                }
                 
                 
            }
            // 按年龄分组
            List<Person> persons = Arrays.asList(new Person("1",1),
            new Person("1",1),new Person("1",2),new Person("1",3));
            Map<Integer, List<Person>> personGroup = persons.stream()
            .collect(Collectors.groupingBy(Person::getAge));
            personGroup.keySet().stream().forEach(w -> System.out.println(personGroup.get(w)));
        }
     
         
    }

    参考资料:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/

  • 相关阅读:
    妇女节 or 女人节 ?
    闲话电子商店(eshop)的设计和经营 (1)
    网站发展的若干思考
    历史上的今天
    升级到.net2.0失败
    冰峰战术
    【Struts2复习知识点十三】模块包含——配置struts.xml
    【Struts2复习知识点十二】web元素request session application等
    【Hibernate3.3】 slf4j 说明。
    【Struts2复习知识点二十四】 拦截器
  • 原文地址:https://www.cnblogs.com/jnba/p/10563105.html
Copyright © 2011-2022 走看看