Stream常用操作符

2021-02-18  本文已影响0人  小耗子_20da

1、stream创建

1.1、集合转stream
    List<User> list = new ArrayList<>();
    Stream<User> stream = list.stream();
    Stream<User> parallelStream = list.parallelStream();
1.2、数组转stream

数组不能转并行流

    int[] array = {1, 2, 3, 4, 5};
    IntStream intStream = Arrays.stream(array);
    Arrays.stream(array);
1.3、用Stream中静态方法创建

1.3.1、Stream.of

    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

1.3.2、Stream.iterate: 以seed为起始值,根据UnaryOperator中返回值不断迭代

    Stream<Integer> stream2 = Stream
            .iterate(7, new UnaryOperator<Integer>() {
                @Override
                public Integer apply(Integer integer) {
                    return integer + 3;
                }
            })
            .limit(4);
    //7,10,13,16
    stream2.forEach(System.out::println);

1.3.3、Stream.generate()不断获取Supplier中 get()方法返回值

    Stream<Double> stream3 = Stream.generate(new Supplier<Double>() {
        @Override
        public Double get() {
            return Math.random();
        }
    }).limit(3);
    //0.014464768543508866 ,0.07501969315371027 ,0.2563750250586957
    stream3.forEach(System.out::println);
1.4、使用 BufferedReader.lines() 方法,将每行内容转成流
    BufferedReader reader = new BufferedReader(new FileReader("F:\\test_stream.txt"));
    Stream<String> lineStream = reader.lines();
    lineStream.forEach(System.out::println);
1.5、使用 Pattern.splitAsStream() 方法,将字符串分隔成流
    Pattern pattern = Pattern.compile(",");
    Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");
    stringStream.forEach(System.out::println);

2、中间操作符

2.1、筛选与切片
2.2、映射
2.3、排序
2.4、消费

peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。

3、终止操作符

3.1、匹配、聚合操作
    Optional<User> reduce = stream.reduce(new BinaryOperator<User>() {
        @Override
        public User apply(User user, User user2) {
            //第一次:user为流中第一个元素,user2为流中第二个元素
            //第二次:user为第一次apply返回的元素,user2为流中第三个元素
            //第三次:user为第二次apply返回的元素,user2为流中第四个元素
            //以此类推,并行流的顺序没有规律,但是最终的结果和串行流的结果是一样的
            System.out.println("user = " + user.name + "   user2 = " + user2.name);
            return new User(user.name + user2.name, 1, 100);
        }
    });
    System.out.println(reduce);
    User identity = new User("曹操", 1, 50);
    User user = stream.reduce(identity, new BinaryOperator<User>() {
        @Override
        public User apply(User user, User user2) {
            //串行流:
            //第一次:user为identity,user2为流中第一个元素
            //第二次:user为第一次apply返回的元素,user2为流中第二个元素
            //第三次:user为第二次apply返回的元素,user2为流中第三个元素
            //以此类推。。。
            
            // 并行流
            //首先会用 identity 与 流中所有元素规约一次,即user = identity ,user2 为流中任意元素
            //然后用上次规约出来的结果再次两两规约,以此类推。。。
            
            System.out.println(Thread.currentThread().getName()+" user = " + user.name + "   user2 = " + user2.name);
            return new User(user.name + user2.name, 1, 100);
        }
    });
    System.out.println(user);
    User identity = new User("曹操", 1, 50);
    User user = stream.reduce(identity,
            new BiFunction<User, User, User>() {
                @Override
                public User apply(User user, User user2) {
                    System.out.println(Thread.currentThread().getName() + " BiFunction  user = " + user.name + "   user2 = " + user2.name);
                    return new User("BiFunction" + user.name + user2.name, 1, 100);
                }
            },
            new BinaryOperator<User>() {
                @Override
                public User apply(User user, User user2) {
                    //串行流中该方法不会被回调,只会回调BiFunction中的apply方法,结果和2形参的reduce方法一样

                    //并行流
                    //首先在BiFunction中将identity与流中元素逐一规约,生成一个新的流
                    //然后将新的流在BinaryOperator中两两规约
                    System.out.println(Thread.currentThread().getName() + " BinaryOperator  user = " + user.name + "   user2 = " + user2.name);
                    return new User("BinaryOperator" + user.name + user2.name, 1, 100);
                }
            });
    System.out.println(user);

4、收集(collect)

4.1、归集
    List<User> toList = stream.collect(Collectors.toList());
    Set<User> toSet = stream.collect(Collectors.toSet());
    ArrayList<User> toCollection = stream.collect(Collectors.toCollection(ArrayList::new));

    HashMap<String, User> toMap = stream.collect(Collectors.toMap(
            user -> user.name,//第一个函数时接口返回的是map 的key
            user -> user,//第二个函数时接口返回的是map 的value
            (user, user2) -> user2,//两个元素键值对冲突时的解决方案
            HashMap::new
    ));
    //并行的,形参和toMap一样一样的
    ConcurrentMap<String, User> concurrentMap = stream.collect(Collectors.toConcurrentMap(
            user -> user.name,
            user -> user,
            (user, user2) -> user2,
            ConcurrentHashMap::new
            )
    );
4.2、数据统计

Collectors提供了一系列用于数据统计的静态方法:

    @Test
    public void count() {
        List<User> list = new ArrayList<>();
        list.add(new User("吕布", 1, 48));
        list.add(new User("貂蝉", 2, 37));
        list.add(new User("刘备", 1, 56));
        list.add(new User("孙尚香", 2, 18));
        list.add(new User("周瑜", 2, 27));
        list.add(new User("小乔", 2, 22));
        
        // 统计数量,等效于list.stream().count(); 或list.size();
        Long count = list.stream().collect(Collectors.counting());
        // 求平均值
        Double average = list.stream().collect(Collectors.averagingDouble(user -> user.age));
        // 求最大值,等效于 list.stream().map(user -> user.age).max(Integer::compare);
        Optional<Integer> max = list.stream().map(user -> user.age).collect(Collectors.maxBy(Integer::compare));
        // 求和,等效于list.stream().mapToInt(user -> user.age).sum();
        Integer sum = list.stream().collect(Collectors.summingInt(user -> user.age));
        // 一次性统计所有信息
        DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(user -> user.age));

        System.out.println("总数:" + count);//总数:6
        System.out.println("平均值:" + average);//平均值:34.666666666666664
        System.out.println("求和:" + sum);//求和:208
        System.out.println("所有统计:" + collect);//所有统计:DoubleSummaryStatistics{count=6, sum=208.000000, min=18.000000, average=34.666667, max=56.000000}
    }
4.3、分组分区
    @Test
    public void group() {
        List<User> list = new ArrayList<>();
        list.add(new User("诸葛亮", 1, 48, "法师"));
        list.add(new User("貂蝉", 2, 37, "法师"));
        list.add(new User("鲁班", 1, 56, "射手"));
        list.add(new User("刘禅", 1, 18, "辅助"));
        list.add(new User("韩信", 1, 27, "打野"));
        list.add(new User("孙尚香", 2, 22, "射手"));

        //{辅助=[User{name='刘禅', sex=1, age=18}], 打野=[User{name='韩信', sex=1, age=27}], 射手=[User{name='鲁班', sex=1, age=56}, User{name='孙尚香', sex=2, age=22}], 法师=[User{name='诸葛亮', sex=1, age=48}, User{name='貂蝉', sex=2, age=37}]}
        Map<String, List<User>> groupingBy = list.stream().collect(Collectors.groupingBy(user -> user.role));//按user.role分组
        
        //{辅助={1=[User{name='刘禅', sex=1, age=18}]}, 打野={1=[User{name='韩信', sex=1, age=27}]}, 射手={1=[User{name='鲁班', sex=1, age=56}], 2=[User{name='孙尚香', sex=2, age=22}]}, 法师={1=[User{name='诸葛亮', sex=1, age=48}], 2=[User{name='貂蝉', sex=2, age=37}]}}
        Map<String, Map<Integer, List<User>>> collect = list.stream().collect(Collectors.groupingBy(
                user -> user.role,//按user.role分组
                Collectors.groupingBy(user -> user.sex)//分组中再按 user.sex分组
        ));
        HashMap<String, Map<Integer, List<User>>> collect1 = list.stream().collect(Collectors.groupingBy(
                user -> user.role,//按user.role分组
                HashMap::new,//返回指定map,不指定则是返回Map对象
                Collectors.groupingBy(user -> user.sex)//分组中再按 user.sex分组
        ));

        //{false=[User{name='刘禅', sex=1, age=18}, User{name='孙尚香', sex=2, age=22}], true=[User{name='诸葛亮', sex=1, age=48}, User{name='貂蝉', sex=2, age=37}, User{name='鲁班', sex=1, age=56}, User{name='韩信', sex=1, age=27}]}
        Map<Boolean, List<User>> partitioningBy = list.stream().collect(Collectors.partitioningBy(user -> user.age > 25));
    }
4.4、接合(joining)
    //由于joining接收的是CharSequence类型,所以需要映射一下
    list.stream().map(user -> user.name).collect(Collectors.joining());
    list.stream().map(user -> user.name).collect(Collectors.joining("-"));
    list.stream().map(user -> user.name).collect(Collectors.joining("-", "前缀", "后缀"));
4.5、规约(reducing)

规约和stream的规约是一样的,这里不做笔记了

4.6、映射(mapping)
    //等效于 list.stream().map(user -> user.name).collect(Collectors.toList());
    list.stream().collect(Collectors.mapping(user -> user.name, Collectors.toList()));
4.7、收集后再处理(collectingAndThen)
    String collect = list.stream().collect(
            Collectors.collectingAndThen(
                    Collectors.mapping(user -> user.name, Collectors.joining("-")),
                    s -> "apply " + s
            ));

    System.out.println(collect);// apply 诸葛亮-貂蝉-鲁班-刘禅-韩信-孙尚香
上一篇 下一篇

猜你喜欢

热点阅读