当前位置:   article > 正文

08-Stream流计算

stream流计算
Stream流计算

用传统for循环处理复杂计算代码虽然也不是很难,但代码就显得冗余了。跟Stream相比就显而易见。配合出现的Lambda表达式,给我们操作集合类提供了方便。

在这里插入图片描述

定义
Stream将要处理的元素集合看作一种流,在流的过程。借助Stream对流中的元素进行操作,比如筛选、排序、集合等‘
Stream可以由数组或集合创建。对流的操作分为两种:

  1. 中间操作,每次返回一个新的流,可以有多个
  2. 终端操作,每个流只能进行一次终端操作,终端操作后流无法再次使用,终端操作后会产生一个新的集合或值

另外,Stream有几个新的特性:

  1. Stream不存储元素,而是按照特定的规则对数据进行计算,一般会输出i结果。
  2. Stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
  3. Stream具有延迟特性,只有终端操作时,中间操作才会执行
Stream可以通过集合数组创建

stream()

 List<String> list=new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        Stream<String> stream = list.stream();//创建一个顺序流
        System.out.println(stream);

       //创建一个并行流
        Stream<String> stringStream = list.parallelStream();
        System.out.println(stringStream);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果:
在这里插入图片描述

用数组创建流

Arrays.stream();

  int [] array={1,3,5,7,9};
        IntStream stream1 = Arrays.stream(array);
        System.out.println(stream1);
  • 1
  • 2
  • 3

结果:
在这里插入图片描述

Stream静态方法

of(); 、 iterator();、generate();
在这里插入图片描述

        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
        System.out.println(integerStream);
        
        System.out.println("=================");
        Stream<Integer> limit = Stream.iterate(1, (x) -> x + 2).limit(5);//打印从1 每次加2,数量为5
        limit.forEach(System.out::println);
        System.out.println("=================");
        
        Stream<Double> limit1 = Stream.generate(Math::random).limit(3);//随机生成个3个小数
        limit1.forEach(System.out::println);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果:
在这里插入图片描述

Stream和parallelStream的区别
  1. Stream事顺序流,由主线程按顺序对流进行操作。
  2. parallelStream是并行流,内部以多线程并执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求
    筛选集合中的奇数,两种处理方式是不同的:

在这里插入图片描述
如果流中的数据量足够大,并行流可以加快速度,除了直接创建并行流。还可以通过parallel()把顺序流转换成并行流:

在使用stream之前,先理解Optional的概念

Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法返回true,调用get()方法返回该对象。
详解见 :菜鸟教程Java 8 Optional类

List list=new ArrayList<>();
        list.add(8);
        list.add(9);
        list.add(1);
        list.add(3);
        //筛选大于6 的第一个数字
        Optional<Integer> s= list.stream().parallel().filter(x->x>6).findFirst();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
遍历
 List<Integer> list= Arrays.asList(1,2,3,4,5,6,7,8,9);
        //筛选所有大于7的数字
        list.stream().filter(x->x>7).forEach(System.out::println);
        System.out.println("========");

        //匹配第一个大于1的数字
        Optional<Integer> first = list.stream().filter(x->x>1).findFirst();
        System.out.println(first.get());
        System.out.println("========");

        //匹配任意一个大于1的数字
        Optional<Integer> any = list.parallelStream().filter(x -> x > 1).findAny();
        System.out.println(any.get());
        System.out.println("========");

        boolean b = list.stream().anyMatch(x -> x > 7);
        System.out.println(b);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

结果:
在这里插入图片描述

筛选

筛选是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中。
在这里插入图片描述

将用多个案例帮助理解使用Stream

Person类:

@Data
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;
    private String sex;
    private Double salary;
    private String area;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  List<Person> personList=new ArrayList<>();
        personList.add(new Person("张三",20,"男",8900.00,"江苏盐城"));
        personList.add(new Person("李四",21,"男",7000.00,"江苏镇江"));
        personList.add(new Person("王五",22,"男",7800.00,"江苏常州"));
        personList.add(new Person("张丽",23,"女",8200.00,"江苏淮安"));
        personList.add(new Person("王茜",24,"女",9500.00,"江苏南通"));
        personList.add(new Person("陈涵",22,"女",7900.00,"江苏南京"));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

筛选员工中工资高于8000的人,形成新的集合。形成的集合使用collect()收集。

List<Person> collect =personList.stream.filter(person-> person.getSalary()>8000).collect(Collector.toList);
System.out.println(collect);
  • 1
  • 2

结果:
在这里插入图片描述

聚合

max、min、result
在这里插入图片描述

案例1:获取String 中最长的元素值

  List<String> ListA=Arrays.asList("Admin","Test","Manager","Develop");
  Optional<String>max=ListA.stream.max(Compatrator.comparing(String::length));
  System.out.println(max.get());
  • 1
  • 2
  • 3

结果:
在这里插入图片描述
案例2 获取集合中最大的值

 List<Integer> integerList=Arrays.asList(1,3,5,7,2,4);
 
 Optional<Integer> max=integerList.stream.max(Integer::compareTo);
 System.out.println(max.get());
  • 1
  • 2
  • 3
  • 4

结果:
在这里插入图片描述
案例3
获取员工中最高工资的人

Optional<Person> max=personList.stream.max(Comparator.comparing(person->person.getSalary()));
System.out.println(max.get());
//第二种方法
Optional<Person> max1=personList.stream.max(Comparator.comparingDouble(Person::getSalary)));
System.out.println(max1.get());
  • 1
  • 2
  • 3
  • 4
  • 5

结果:
在这里插入图片描述
案例四
计算集合中元素大于6的个数

List<Integer> integerList=Arrays.asList(1,2,3,4,5,6,7,8,9);

Long count=integerList.stream.filter(i->i>6).count();
System.out.println(count);
  • 1
  • 2
  • 3
  • 4

结果:
在这里插入图片描述

3.4映射

map/flatmap
可以将一个流的元素按照一定的规则映射到另一个流的元素上,分为map和flatmap

  1. map:接受一个函数作为参数,将其映射成一个新的元素
  2. flatMap:接收一个函数作为参数,将流中的每一个值都换成另一个流,然后将所有的流连接起来变成另一个流。
    在这里插入图片描述
    案例1英文字符数组元素全部改为大写,整数数组每个元素+3
String[] arr={"cdc","cwerec","ggfb"};
List<String> collect=Arrays.asList(arr).stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect);

List<Integer> integerList=Arrays.asList(1,5,7);
List<Integer>collect1=integer.stream.map(i->i+3).collect(Collector.toList));
System.out.println(collect1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果:
在这里插入图片描述
案例2: 将员工的工资全部增加1000

List<Person> newList=personList.stream.map(person->{
 person.setSalary(person.getSalary+1000.00);
 return person;
}).collect(Collector.toList);

System.out.println(newList);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果:
在这里插入图片描述
案例3
将两个字符组合成一个新的字符数组

 List<String> list= Arrays.asList("m,k,l,a","1,3,5,7");
        List<String> list_new1 = list.stream().flatMap(words -> {
            String[] split = words.split(",");
            Stream<String> list_new = Arrays.stream(split);
            return list_new;
        }).collect(Collectors.toList());

        System.out.println("原始list"+list);
        System.out.println("新的"+list_new1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结果:
在这里插入图片描述

3.5归约

归约也就是缩减,将一个流缩减成一个值,能实现对集合的求值、求乘机和求和、求最值的操作

案例一:求Integer集合的元素之和、乘机和最大值

        List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
        Optional<Integer> sum = integers.stream().reduce(Integer::sum);

        Optional<Integer> multi = integers.stream().reduce((x, y) ->x*y);

//方式1
        Integer max = integers.stream().reduce(1, Integer::max);
        //方式2
        Optional<Integer> max1 = integers.stream().max(Comparator.comparing(Integer::intValue));
        //方式3
        Optional<Integer> max2 = integers.stream().max(Integer::compareTo);

        System.out.println("和"+sum.get());
        System.out.println("乘"+multi);
        System.out.println("最大值"+max2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

结果:
在这里插入图片描述
案例二:
求所有员工的工资之和和最高的工资

    List<Person> personList=new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        personList.add(new Person("Owen", 9500, 25, "male", "New York"));
        personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

        Optional<Integer> sum = personList.stream().map(Person::getSalary).reduce(Integer::sum);
        Optional<Person> max = personList.stream().max(Comparator.comparing(Person::getSalary));
        System.out.println("总和"+sum);
        System.out.println("最大值"+max.get().getSalary());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

结果:
在这里插入图片描述

3.6 收集(collect)

collect,收集,把流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。

  • collect主要依赖java.util.stream.Collectors类内置的静态方法。

3.6.1
归集(toList/toSet/toMap)
因为流不存储数据,那么流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toList、toSet和toMap比较常用,另外还有toCollection、toConcurrentMap等复杂的一些用法。

案例一:

  List<Integer> list=Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);
        List<Integer> new_list = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
        Set<Integer> new_Set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
        Map<String, Person> new_Map = personList.stream().filter(person ->
                person.getSalary() > 8000
        ).collect(Collectors.toMap(Person::getName, person -> person));

        System.out.println("list"+new_list);
        System.out.println("set"+new_Set);
        System.out.println("map"+new_Map);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果:
在这里插入图片描述
3.6.2统计(count/averaging)
Collectors提供了一系列用于数据统计的静态方法:

  • 计数count
  • 平均值:averagingint、averagingLong、averagingDouble
  • 最值:maxBy、minBy
  • 求和:summingInt 、summingLong、summingDouble
  • 统计以上所有:summarizingInt、summarizingLong、summarizingDouble

案例:统计员工人数、平均工资、工资总额、最高工资等

  Long count = personList.stream().collect(Collectors.counting());
        Double salary = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
        Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compareTo));
        IntSummaryStatistics sum = personList.stream().collect(Collectors.summarizingInt(Person::getSalary));
        DoubleSummaryStatistics sumAll = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

        System.out.println("数量"+count);
        System.out.println("平均工资"+salary);
        System.out.println("最高工资"+max);
        System.out.println("工资之和"+sum);
        System.out.println("一次性信息"+sumAll);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

结果:
在这里插入图片描述

3.6.3分组(partitioningBy/groupingBy)
  • 分区:将stream按条件分为两个Map,比如员工按薪资是否高于8000分为部分
  • 分组:将集合分为多个Map,比如员工按性别分组,有单级分组和多级分组。
    在这里插入图片描述
    案例
    将员工按薪资是否高于8000分为两部分;将员工按性别和地区分组
        Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
        Map<String, List<Person>> part1 = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        Map<String, Map<String, List<Person>>> part3 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getSex)));

        System.out.println("员工按薪资是否大于8000分组情况"+part);
        System.out.println("员工按性别分组情况"+part1);
        System.out.println("员工按性别、地区分组情况"+part3);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果:
在这里插入图片描述

3.6.4接合(joining)

joining可以将stream中的元素用特定的连接符连接成一个字符串。

        String joinName = personList.stream().map(person -> person.getName()).collect(Collectors.joining("-"));

        List<String> list = Arrays.asList("A", "B", "C");
        String collect = list.stream().collect(Collectors.joining("+"));

        System.out.println("所有员工的姓名"+joinName);
        System.out.println("拼接后的字符串"+collect);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果:
在这里插入图片描述

3.6.5归约(reducing)

Collectors类提供的reducing方法,相比于stream本身的reduce方法,增加了对于自定义归约的支持。

Optional<Integer> sumSalary = personList.stream().map(Person::getSalary).reduce(Integer::sum);
        Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
        System.out.println("员工薪资总和"+sumSalary.get());
        System.out.println("员工薪资总和"+sum);
  • 1
  • 2
  • 3
  • 4

结果:
在这里插入图片描述

3.7排序(sorted)
  • sorted():自然排序,流中元素实现Comparable
  • sorted(Comparator com):Comparator排序器自定义排序

案例:将员工按工资由高到低(工资一样则年龄由大到小)排序

 //自然排序
        List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary))
                .map(Person::getName).collect(Collectors.toList());

        //倒序排序
        List<String> newList1 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
                .map(Person::getName).collect(Collectors.toList());

        //先按工资再按年龄升序排序
        List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary)
                        .thenComparing(Person::getAge)).map(Person::getName)
                .collect(Collectors.toList());

        System.out.println("升序排序"+newList);
        System.out.println("降序排序"+newList1);
        System.out.println("先按工资再按年龄升序排序"+newList2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

结果:
在这里插入图片描述

3.8提取、组合

流也可以进行合并、去重、限制、跳过等操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

        String[] arr1={"a","b","c","d"};
        String[] arr2={"d","e","f","g"};

        //去重
        List<String> distinct = Stream.concat(Stream.of(arr1), Stream.of(arr2)).
                                distinct().collect(Collectors.toList());

        //限制从流中获取n个数字
        List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());

        List<Integer> collect1 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());

        System.out.println("流合并"+distinct);
        System.out.println("limit"+collect);
        System.out.println("skip"+collect1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

结果:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/537074
推荐阅读
相关标签
  

闽ICP备14008679号