美文网首页基础原理
Stream并发和分组

Stream并发和分组

作者: shz_Minato | 来源:发表于2019-01-19 10:00 被阅读33次

    一 Stream的flatMap

     操作符定义

     函数签名:Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

    R 是新流中元素的类型
    T 是旧流中的元素的类型
    Function的意义是:接收一个参数,返回一个结果。
    
    连接起来就是:flatMap将旧流中类型为T的每个元素,转为一个新的子流,子流中元素的
    类型是R,并将子流汇总为总流
    
    旧流中有几个元素,就会有几个子流
    

     实例:将数组交叉输出

    public class StreamTest {
        public static void main(String[] args) {
            //将每个stringList元素+integerList元素前缀输出
            List<Integer> integerList = Arrays.asList(1, 2, 3, 4);
            List<String> stringList = Arrays.asList("一", "二", "三", "四");
    
            integerList.stream()
                    .flatMap(it->stringList.stream().map(item->it+" "+item))
                    .forEach(System.out::println);
    
            //相当于子流是stringList元素加前缀输出
            
        }
    }
    
    

    二 Stream的并行流

     Stream支持并行和串行的操作,串行是单线程的比较耗时,并行时多线程运行,运行效率高。Stream并行的操作比较简单,就是在流中添加parallel()操作。
     以排序为例

    public class StreamTest {
        public static void main(String[] args) {
           
            List<UUID> list = new ArrayList<>(5000000);
            for (int i = 0; i < 5000000; i++) {
                list.add(i, UUID.randomUUID());
            }
    
    
            long startTime= System.currentTimeMillis();
            list.stream()
                    .sorted()
                    .count();
            long endTime=System.currentTimeMillis();
            System.out.println((endTime-startTime));
    
    
            startTime= System.currentTimeMillis();
            list.stream()
                    .parallel()//添加该操作符即可
                    .sorted()
                    .count();
            endTime=System.currentTimeMillis();
            System.out.println((endTime-startTime));
            
            //运行结果
            3698
            1401 //并行更加有效率
    
        }
    }
    

    三 Stream的分组和分区

     Stream的分组和分区,需要的操作符是collect
     操作符的签名:R collect(Collector<? super T, A, R> collector)

    R 是返回结果的类型
    T 流中元素的类型
    A 累加器的类型
    
    该操作的含义:使用collector对流中的元素进行聚合的操作,collector封装了
    collect(Supplier, BiConsumer, BiConsumer)中的参数,用于重用收集策略,比如toList,和收集操作,比如分组和分区。
    
    

     Collector:聚合操作,将流中元素收集至一个可变的容器中(List,Map等)。常见的聚合操作有:将元素添加至集合,拼接字符串,常见的数字计算(求和、最值、均值)等,Collectors中有类似的工具类方法。
    Collector功能的实现主要是通过四个抽象方法:
       supplier():创建容器结果
       accumulator():将元素添加至容器中
       combiner():将两个容器合二为一(并行时)
       supplier():可选的转换操作

     分组实现 Collectors的groupingBy方法

    static <T, K, D, A, M extends Map<K, D>>
        Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
                                      Supplier<M> mapFactory,
                                      Collector<? super T, A, D> downstream) 
        
        参数介绍
            M 是返回结果的类型,是Map的子类。分组的结果是Map
            T 是流中元素的类型
            K 是结果Map的key的类型
            A 是结果value的类型
            D 是结果Map的value的容器结果类型
            
            classifier是将流中元素转为结果Map的key
            mapFactory是结果的map
            downstream是整理map的value,因为有可能是多级分组,所以也是Collector
            
    

     分组案例 将List<String> 按其长度分组

    public class StreamTest {
        public static void main(String[] args) {
    
    
            List<String> stringList = Arrays.asList("Hello", "World", "Java", "I");
    
            TreeMap<Integer, List<String>> collect = stringList.stream()
                    .collect(Collectors.groupingBy(
                            String::length,//key是字符串的长度
                            TreeMap::new,//结果是TreeMap
                            Collectors.toList()));//value是list
            System.out.println(collect);
    
    
        }
    }
    
    

     分区实现 Collectors的partitioningBy方法
     分区是分组的特殊化,就是按照predicate分成两组而已

    //任然上例为例,将长度改为长短。凡是长度小4的在一组,长度大于5的在另外一组
    
    public class StreamTest {
        public static void main(String[] args) {
    
    
            List<String> stringList = Arrays.asList("Hello", "World", "Java", "I");
    
            Map<Boolean, List<String>> map = stringList.stream()
                    .collect(Collectors.partitioningBy(
                            it -> it.length() > 4,//predicate的条件
                            Collectors.toList()
                    ));
            System.out.println(map);
    
    
        }
    }
    
    

    相关文章

      网友评论

        本文标题:Stream并发和分组

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