Java8新特性Stream的简单使用
Stream是使用一个类似用SQL语句从数据库查询数据的直观方法来提供一种对Java集合运算和表达的高阶抽象。
使用Stream可以写出高效率、干净、简洁的代码。
什么是Stream?
Stream(流) 是一个来自数据源的元素队列并支持聚合操作
-
元素是特定类型的对象、形成一个队列。Java中的Stream并不会存储元素,而是按需计算。
-
数据源 的来源。可以是集合、数组、I/O channel,产生器generator等。
-
聚合操作 类似SQL语句一样的操作,比如filter,map,reduce,find,match,sorted等。
和以前的Collection操作不同,Stream操作还有两哥基础的特征:
-
Pipelining:中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流式风格(fluent style)。这样子做可以对操作进行优化,比如延迟执行(laziness)和短路(short-circuiting)。
-
内部迭代:以前对集合遍历时通过Iterator或者For-Each的方式,显式的在集合外部进行迭代,这叫做外部迭代。Stream提供了内部迭代的方式,通过范问者模式(Visitor)实现。
生成流
在java8中,集合接口又两个方法来生成流:
- stream() - 为集合创建串行流。
- parallelStream() - 为集合创建并行流。
Stream的方法
forEach
Stream提供了新的方法’forEach’来迭代流中的每个数据。
// 使用forEach输出10个随机数
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
map
map方法用于映射每个元素到对应的结果。
// 定义一组数据
List<Integer> numbers = Arrays.asList(3, 2, 2, 4, 7, 3, 5);
// 获取对应的平方
// .distinct() 表示去除重复的数,使每个数只出现一次!
List<Integer> squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
System.out.println(squaresList.toString());
结果:[9, 4, 16, 49, 25]
filter
filter方法用于通过设置的条件去过滤出元素。
// 定义一组包含空字符串的数据
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "123", "","jkl");
// 获取集合中为空字符串的数量
// 代码中的string 可以是容易一个定义的变量 比如: x -> x.isEmpty() 结果也是一样的。
long count = strings.stream().filter(string -> string.isEmpty()).count();
System.out.println(count);
结果: 2
limit
limit方法用于获取指定数量的流。
// 使用forEach输出20个随机数
Random random = new Random();
random.ints().limit(20).forEach(System.out::println);
sorted
sorted方法用于对流进行排序。
// 使用forEach输出10个随机数
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
并行(parallel)程序
parallelStream是流并行处理程序的代替方法。
// 定义一组数据
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "123", "","jkl");
// 获取空字符串的数量
count = strings.parallelStream().filter(string -> string.isEmpty()).count();
System.out.println(count);
结果:2
Collectors
Collectors类实现了很多归约操作。
// 定义一组数据
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "123", "","jkl");
// 获取条件过滤后的列表
List<String> filtered = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表 " + filtered);
// 获取条件过滤后的合并字符串
String mergedString = strings.stream().filter(m -> !m.isEmpty()).collect(Collectors.joining());
System.out.println("合并字符串:" + mergedString);
结果:
筛选列表 [abc, bc, efg, 123, jkl]
合并字符串:abcbcefg123jkl
统计
另外,一些产生统计结果收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。
// 定义一组数据
List<Integer> numbers = Arrays.asList(3, 2, 2, 4, 7, 3, 5);
// 其他基本类型用法几乎都差不多
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
// .getMax() 获取最大值
System.out.println("列表中最大的值:" + stats.getMax());
// .getMin() 获取最小值
System.out.println("列表中最小的值:" + stats.getMin());
// .getSum 获取总和
System.out.println("所有数之和:" + stats.getSum());
// .getAverage() 获取平均数
System.out.println("平均数:" + stats.getAverage());