Stream API —— Java 8 的新特性
简介
Java 8 引入了一个新的数据操作方式,及Stream API流式处理。在对数据集合进行操作时能够通过更简单的方式进行数据的筛选等操作。基于Lambda表达式,能够通过非常简洁的代码实现数据的操作。接下来将详细介绍Stream API。
1.什么是Stream API
Stream API可以让你以一种声明式的方式处理数据集合。它支持并行操作,可以极大地提高数据处理的效率。Stream不是数据结构,而是一个可以进行聚合操作的数据集合视图。
简单来说Stream类似于一个多级过滤器,source产生数据流,并通过一些中间操作,比如过滤,转换,限制等,最后结束对流的操作。
2.为什么需要Stream
Stream API 主要通过Lambda表达式完成,不仅提高了程序运行效率和可读性,同事Stream API中自带的并行流使并发处理集合的难度降低。在无需创建额外线程的情况下就能够写出高并发的程序。
此外,流的另一个特性是可无限性,即使用Stream时,数据源可以是无线大的。基于这种特性,可以在Java企业开发过程中提高数据的处理速度,从而实现一定程度上的并发。
实现Stream
在Java中通过集合对象的Stream()函数即可实现,实现过程如下:
List<Integer> arr = Arrays.asList(1,11,12,13,21,22,23,11);
Stream<Integer> stream = arr.stream();
1.Stream执行流程
上面提到,Stream将会对数据进行一系列操作,那其中都有哪些操作呢,接下来将逐个说明
1.1 filter
过滤元素,接收一个Predicate参数。
stream.filter(s -> s.equals(1)).forEach(System.out::println);//输出结果为1
1.2 map/flatmap
map用于转换元素,接收一个Function参数
stream.map(s -> s.toString()).forEach(System.out::println); //将集合中数组转为字符串输出
flatmap即扁平化映射,主要操作是将多个stream对象连接成一个
List<List<Integer>> ints=new ArrayList<>(Arrays.asList(Arrays.asList(1,2),
Arrays.asList(3,4,5)));
List<Integer> flatInts=ints.stream().flatMap(Collection::stream).
collect(Collectors.toList());
1.3 distinct
去除集合中重复元素
stream.distinct().forEach(System.out::println); //输出1,11,12,13,21,22,23
1.4 sorted
sorted即排序操作,默认为从小到大。sorted中包含了一个重载,若在使用sorted时没有传递参数,那么元素就需要实现 Comparable<T>
,也可以在使用sorted时传入
Stream<T> sorted(Comparator<? super T> comparator);
Stream<T> sorted();
1.5 peek
peek和forEach一样是遍历功能,但是是中间操作,使用peek时接收一个参数
Stream<T> peek(Consumer<? super T> action);
1.6 limit
limit为裁剪操作,限制了数据流中元素的数量,当调用limit(n)时,数据流中将会包含前n个元素。
List<Integer> arr = Arrays.asList(1,11,12,13,21,22,23,11);
Stream<Integer> stream = arr.stream();
stream.limit(3).forEach(System.out::println);//输出1,11,12
1.7 skip
skip即跳过前面多少个元素,和limit比较像,limit是保留前面多少个元素 。
List<Integer> arr = Arrays.asList(1,11,12,13,21,22,23,11);
Stream<Integer> stream = arr.stream();
stream.skip(3).forEach(System.out::println);//输出13,21,22,23,11
2.终端操作
终端操作是用户希望Java在IDE的终端或计算机程序的终端进行怎样的操作,同时也是Stream操作流的结束点。
2.1 forEach
forEach用于执行副作用,接收一个Consumer参数。
上述操作演示forEach的操作
2.2 collect
collect用于收集Stream中的元素,返回一个结果。
List<Integer> list = stream.collect(Collectors.toList());
for (Integer i : list) {
System.out.println(i);
}
//通过collect转换后可以正常遍历输出
2.3 reduce
reduce将会把stream中的对象组合并返回一个值,具体操作如下
Optional<String> reduced = stream.reduce((s1, s2) -> s1 + " " + s2);
2.4 toArray
toArray和List.toArray比较像,包含一个重载,并返回一个Object[]对象,用法如下
Student[] studentArray = students.stream().skip(3).toArray(Student[]::new);
2.5 min/max
找出数据流中的最小/最大值,使用时需传入一个Comparator。
Optional<Integer> min = stream.min(Comparator.comparing(Integer::byteValue));
Optional<Integer> max = stream.max(Comparator.comparing(Integer::byteValue));
2.6 count
返回数据流中的元素个数。
List<Integer> arr = Arrays.asList(1,11,12,13,21,22,23,11);
System.out.println(stream.count());//输出结果为8
2.7 anyMatch/allMatch/noneMatch
判断数据流中元素的匹配情况,函数接收一个Predicate参数。
boolean test = integers.stream().anyMatch(x->x>3);
2.8 findFirst/findAny
获取数据流中元素。
int res = integers.stream().findAny().get();
本文介绍了Stream API的基本原理以及常见的使用方法,其中还有一些方法并未提及,大家可以自行探索。此外,Stream API可以通过调用多个处理方法对数据流进行并行处理,提高了数据处理的效率。
总结
博主大学的专业是大数据专业,在校时学习了Python数据预处理技术。其中最常使用的工具是Python的DataFrame。在对Stream API进行深入了解后,博主觉得这两者有许多相似之处,总体来说都是对数据流的处理。但Stream API在搭配上自身并行的特性,对数据处理的效率会更高。此外在企业级应用开发过程中,Stream API也在数据流处理、查询、检索等方面提供了更加优秀的性能表现。