JDK 8——聚合操作


  在Java8版本中,JDK包含许多聚合操作(如平均值,总和,最小,最大,和计数),返回一个计算流stream的聚合结果。这些聚合操作被称为聚合操作。JDK除返回单个值的聚合操作外,还有很多聚合操作返回一个collection集合实例。很多的reduce操作执行特定的任务,如求平均值或按类别分组元素。

1. 聚合操作简介

  在开发中,多数情况下会涉及到对集合、数组中元素的操作,在JDK 8之前都是通过普通的循环遍历出每一个元素,然后还会穿插一些if条件语句选择性的对元素进行查找、过滤、修改等操作,这种原始的操作方法虽然可行,但是代码量较大并且执行效率较低。
  为此,JDK 8中新增了一个Stream接口,该接口可以将集合、数组的中的元素转换为Stream流的形式,并结合Lambda表达式的优势来进一步简化集合、数组中元素的查找、过滤、转换等操作,这一新功能就是JDK 8中的聚合操作。
  在程序中,使用聚合操作没有绝对的语法规范,根据实际操作流程,主要可以分为以下3个步骤:
  (1)将原始集合或者数组对象转换为Stream流对象;
  (2)对Stream流对象中的元素进行一系列的过滤、查找等中间操作(Intermediate Operations),然后仍然返回一个Stream流对象;
  (3)对Stream流进行遍历、统计、收集等终结操作(Terminal Operation),获取想要的结果。
  接下来,就根据上面聚合操作的3个步骤,通过一个案例来演示聚合操作的基本用法,具体示例代码如下所示。

 1	import java.util.*;
 2	import java.util.stream.Stream;
 3	public class Example31 {
 4		public static void main(String[] args) {
 5	          // 创建一个List集合对象
 6			List<String> list = new ArrayList<>(); 
 7			list.add("张三");
 8			list.add("李四");
 9			list.add("张小明");
 10			list.add("张阳");
 11			// 1、创建一个Stream流对象
 12			Stream<String> stream = list.stream();
 13			// 2、对Stream流中的元素分别进行过滤、截取操作
 14		       Stream<String> stream2 = stream.filter(i -> i.startsWith("张"));
 15			Stream<String> stream3 = stream2.limit(2);
 16			// 3、对Stream流中的元素进行终结操作,进行遍历输出
 17			stream3.forEach(j -> System.out.println(j));
 18			System.out.println("=======");
 19	         // 通过链式表达式的形式完成聚合操作
 20			list.stream().filter(i -> i.startsWith("张"))
 21						 .limit(2)
 22						 .forEach(j -> System.out.println(j));
 23		}
 24	}

  运行结果如下图所示。 alt   上述示例代码中,先创建了一个List集合,然后根据聚合操作的3个步骤实现了集合对象的聚合操作,对集合中的元素使用Stream流的形式进行过滤(filter)、截取(limit),并进行遍历输出。其中第12~17行代码分步骤详细展示了聚合操作,而第20~22行代码是使用了链式表达式(调用有返回值的方法时不获取返回值而是直接再调用另一个方法)实现了聚合操作,该表达式的语法格式更简洁、高效,这种链式调用也被称为操作管道流。

2. 创建Stream流对象
  在上一小节中,介绍了聚合操作的主要使用步骤,其中首要解决的问题就是创建Stream流对象。聚合操作针对的就是可迭代数据进行的操作,如集合、数组等,所以创建Stream流对象其实就是将集合、数组等通过一些方法转换为Stream流对象。
  在Java中,集合对象有对应的集合类,可以通过集合类提供的静态方法创建Stream流对象,而数组数据却没有对应的数组类,所以必须通过其他方法创建Stream流对象。针对不同的源数据,Java提供了多种创建Stream流对象的方式,分别如下:
  (1)所有的Collections集合都可以使用stream()静态方法获取Stream流对象;
  (2)Stream接口的of()静态方法可以获取基本类型包装类数组、引用类型数组和单个元素的Stream流对象;
  (3)Arrays数组工具类的stream()静态方法也可以获取数组元素的Stream流对象。
  接下来,通过一个案例来学习聚合操作中如何创建Stream流对象,具体示例代码如下所示。

 1	import java.util.*;
 2	import java.util.stream.Stream;
 3	public class Example32 {
 4		public static void main(String[] args) {
 5	          // 创建一个数组
 6			Integer[] array = { 9, 8, 3, 5, 2 };       
 7	          // 将数组转换为List集合
 8			List<Integer> list = Arrays.asList(array); 
 9			// 1、使用集合对象的stream()静态方法创建Stream流对象
 10			Stream<Integer> stream = list.stream();
 11			stream.forEach(i -> System.out.print(i+" "));
 12			System.out.println();
 13			// 2、使用Stream接口的of()静态方法创建Stream流对象
 14			Stream<Integer> stream2 = Stream.of(array);
 15			stream2.forEach(i -> System.out.print(i+" "));
 16			System.out.println();
 17			// 3、使用Arrays数组工具类的stream()静态方法创建Stream流对象
 18			Stream<Integer> stream3 = Arrays.stream(array);
 19			stream3.forEach(i -> System.out.print(i+" "));
 20		}
 21	}

  运行结果如下图所示。 alt   上述示例代码中,先创建了一个数组和一个集合,然后通过三种方式实现了Stream流对象的创建,并通过Stream流对象的forEach()方法结合Lambda表达式完成了集合和数组中元素的遍历。

小提示:
  在JDK 8中,只针对单列集合Collections接口对象提供了stream()静态方法获取Stream流对象,并未对Map集合提供相关方法获取Stream流对象,所以想要用Map集合创建Stream流对象必须先通过Map集合的keySet()、values()、entrySet()等方法将Map集合转换为单列Set集合,然后再使用单列集合的stream()静态方法获取对应键、值集合的Stream流对象。

用户想要评论,请先登录!
  1. tom

    very good blog