为什么要使用Java Stream API?
Stream
是Java8提供的一种更加简便的,对集合类型数据结构的处理API。
这里的集合类型数据结构包括各种数组(int[]
/String[]
等),也包括Collection
和Map
等实现类。
1 传统方式操作集合
在处理集合类型数据结构时,我们通常会遍历得到每个元素,对每个元素进行处理。操作维度在元素的层面。
例如,我们需要统计一串数字中的奇数。
如果是数组数据结构:
int[] nums = new int[]{1,2,3,4,5,6,7,8,9};
int count = 0;
for(int i = 0; i < nums.length; ++i) {
// 1、遍历得到每个元素
int num = nums[i];
// 2、对每个元素进行处理
if (num % 2 == 1) {
++count;
}
}
如果是List数据结构:
List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9);
Iterator<Integer> iterator = nums.iterator();
int count = 0;
while(iterator.hasNext()) {
// 1、遍历得到每个元素
int num = iterator.next();
// 2、对每个元素进行处理
if (num % 2 == 1) {
++count;
}
}
使用增强for
循环:
int count = 0;
// 1、遍历得到每个元素
for(int num: nums) {
// 2、对每个元素进行处理
if(num % 2 == 1) {
++count;
}
}
2 Stream操作集合
在使用Stream
操作集合类型数据结构时,操作维度在流层面。
例如,对于上述例子,使用Stream
进行相同的操作可能如下:
// 1、获取原始数组的流
IntStream intStream = Arrays.stream(nums);
// 2、获取过滤后的流
IntStream filterStream = intStream.filter(num -> num % 2 == 1);
// 3、统计过滤后的流中元素的个数
long count = filterStream.count();
看上去也需要很多行代码,但其实Stream
的操作都是链式的,它还可以写成这样:
long count = Arrays.stream(nums).filter(num -> num % 2 == 1).count();
3 比较
我们可以明显感觉到传统方式和Stream API
操作集合类型数据结构的区别。
传统方式的操作维度在元素的层面:
- 遍历获取每个元素。
- 针对每个元素进行操作。
Stream
的操作维度在流的层面:
- 根据集合类型数据结构创建
Stream
。 - 每次对旧
Stream
操作后会得到新的Stream
。 - 对最后一个
Stream
进行统计/收集等操作,获得最终结果。
Stream
最大的特点是,它是链式操作,可以将多个业务逻辑清晰地分割成多个中间操作。例如,我们可以先去重(distinct()
),然后过滤filter()
,最后排序(sort()
)。
此外,Stream
内部封装了许多模板式代码,通过结合lambda
表达式,极大地简化地代码。
因此,在使用Stream
操作集合时,可以以更高的维度、更简洁的代码、更清晰的业务逻辑进行业务处理,使用起来十分顺畅。