Java8:2万字20个实例玩转集合—筛选、归约、分组、聚合

Java8 Stream
Java8:2万字20个实例玩转集合—筛选、归约、分组、聚合文章插图
先贴上几个案例 , 水平高超的同学可以挑战一下:

  1. 从员工集合中筛选出salary大于8000的员工 , 并放置到新的集合里 。
  2. 统计员工的最高薪资、平均薪资、薪资之和 。
  3. 将员工按薪资从高到低排序 , 同样薪资者年龄小者在前 。
  4. 将员工按性别分类 , 将员工按性别和地区分类 , 将员工按薪资是否高于8000分为两部分 。
用传统的迭代处理也不是很难 , 但代码就显得冗余了 , 跟Stream相比高下立判 。
1 Stream概述Java 8 是一个非常成功的版本 , 这个版本新增的Stream , 配合同版本出现的 Lambda, 给我们操作集合(Collection)提供了极大的便利 。
那么什么是Stream?
Stream将要处理的元素集合看作一种流 , 在流的过程中 , 借助Stream API对流中的元素进行操作 , 比如:筛选、排序、聚合等 。
Stream可以由数组或集合创建 , 对流的操作分为两种:
  1. 中间操作 , 每次返回一个新的流 , 可以有多个 。
  2. 终端操作 , 每个流只能进行一次终端操作 , 终端操作结束后流无法再次使用 。 终端操作会产生一个新的集合或值 。
另外 , Stream有几个特性:
  1. stream不存储数据 , 而是按照特定的规则对数据进行计算 , 一般会输出结果 。
  2. stream不会改变数据源 , 通常情况下会产生一个新的集合或一个值 。
  3. stream具有延迟执行特性 , 只有调用终端操作时 , 中间操作才会执行 。
2 Stream的创建Stream可以通过集合数组创建 。
1、通过 java.util.Collection.stream() 方法用集合创建流
List list = Arrays.asList("a", "b", "c");// 创建一个顺序流Stream stream = list.stream();// 创建一个并行流Stream parallelStream = list.parallelStream();2、使用java.util.Arrays.stream(T[] array)方法用数组创建流
int[] array={1,3,5,6,8};IntStream stream = Arrays.stream(array);3、使用Stream的静态方法:of()、iterate()、generate()
Stream stream = Stream.of(1, 2, 3, 4, 5, 6);Stream stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);stream2.forEach(System.out::println); // 0 2 4 6 8 10Stream stream3 = Stream.generate(Math::random).limit(3);stream3.forEach(System.out::println);输出结果:
0 3 6 90.67961569092719940.19143142088542830.8116932592396652
stream和parallelStream的简单区分: stream是顺序流 , 由主线程按顺序对流执行操作 , 而parallelStream是并行流 , 内部以多线程并行执行的方式对流进行操作 , 但前提是流中的数据处理没有顺序要求 。 例如筛选集合中的奇数 , 两者的处理不同之处:
Java8:2万字20个实例玩转集合—筛选、归约、分组、聚合文章插图
如果流中的数据量足够大 , 并行流可以加快处速度 。
除了直接创建并行流 , 还可以通过parallel()把顺序流转换成并行流:
Optional findFirst = list.stream().parallel().filter(x->x>6).findFirst();3 Stream的使用在使用stream之前 , 先理解一个概念:Optional。
Optional类是一个可以为null的容器对象 。 如果值存在则isPresent()方法会返回true , 调用get()方法会返回该对象 。 更详细说明请见:菜鸟教程Java 8 Optional类
接下来 , 大批代码向你袭来!我将用20个案例将Stream的使用整得明明白白 , 只要跟着敲一遍代码 , 就能很好地掌握 。
Java8:2万字20个实例玩转集合—筛选、归约、分组、聚合文章插图
案例使用的员工类这是后面案例中使用的员工类:
List personList = new ArrayList();personList.add(new Person("Tom", 8900, "male", "New York"));personList.add(new Person("Jack", 7000, "male", "Washington"));personList.add(new Person("Lily", 7800, "female", "Washington"));personList.add(new Person("Anni", 8200, "female", "New York"));personList.add(new Person("Owen", 9500, "male", "New York"));personList.add(new Person("Alisa", 7900, "female", "New York"));class Person { private String name;// 姓名 private int salary; // 薪资 private int age; // 年龄 private String sex; //性别 private String area;// 地区 // 构造方法 public Person(String name, int salary, int age,String sex,String area) {this.name = name;this.salary = salary;this.age = age;this.sex = sex;this.area = area; } // 省略了get和set , 请自行添加}3.1 遍历/匹配(foreach/find/match)Stream也是支持类似集合的遍历和匹配元素的 , 只是Stream中的元素是以Optional类型存在的 。 Stream的遍历、匹配非常简单 。
Java8:2万字20个实例玩转集合—筛选、归约、分组、聚合文章插图