java8新特性,Stream流操作大全之串行流
Stream流简介
1、串行流
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)实现。
2、并行流
parallelStream 是流并行处理程序的代替方法。
可以使用并行流完成一些简单的多线程操作。
一、forEach测试
Stream 提供了新的方法 ‘forEach’ 来迭代流中的每个数据。
//测试 forEach 迭代流中的数据, lamda表达式
public static void testForEach(List<String> list){
//1.输出不为空串的字符串,stream流
System.out.println("测试 forEach 迭代流中的数据,输出不为空串的字符串:");
list.stream().forEach((item)->{
if(item != null && !item.equals("")){
System.out.print(item + ",");
}
});
System.out.println();
//2.输出不为空串的字符串
System.out.println("测试 forEach 迭代流中的数据,找到指定字符串后,退出循环:");
list.forEach((item)->{
if(item != null && !item.equals("")){
System.out.print(item + ",");
}
});
}
public static void main(String[] args){
//初始化数据
List<String> list = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//测试 forEach 迭代流中的数据
testForEach(list);
}
解释:
- 使用lamda表达式的情况下,上面两种方式,都没有办法使用break或者return语句从循环中退出。
- 使用For循环的forEach, 比如for(String s:list){} 则可以在满足条件后使用break语句。
二、map 测试
map 方法用于映射每个元素到对应的结果。
//测试 map 映射流中的数据,
public static void testMap(List<Character> list){
//1.测试 map 映射流中的数据,获取字符的ASCII码
List<Integer> squaresList = list.stream().map((item)->{
return Integer.valueOf(item);
}).collect(Collectors.toList());
System.out.println("测试 map 映射流中的数据,获取字符的ASCII码:" + squaresList);
}
public static void main(String[] args){
//初始化数据
List<Character> list = Arrays.asList('1','a','2','b','3','c');
System.out.println("原始数据:" + list);
//测试 forEach 迭代流中的数据
testMap(list);
}
//结果:
原始数据:[1, a, 2, b, 3, c]
测试 map 映射流中的数据,获取字符的ASCII码:[49, 97, 50, 98, 51, 99]
解释:
map也可用于迭代数组,与forEach的不同在于:
- map的返回值是Stream,也就是说,可以使用收集器收集为新的组数。
- forEach的返回值是void,只能对原数组中的值操作,且与for(int i = 0;i<list.size;++i)这样的循环不同,forEach中迭代的item是拷贝值,不影响原数组的值。
三、filter测试
filter 方法用于通过设置的条件过滤出元素。
public static void testFilter(List<String> list){
List<String> squaresList = list.stream().filter(item->{
return item.contains("a");
}).collect(Collectors.toList());
System.out.println("过滤数据,筛选除字符串中包含a的字符串:"+ squaresList);
}
public static void main(String[] args){
//初始化数据
List<String> list = Arrays.asList("abc","123","ca");
System.out.println("原始数据:" + list);
//测试 forEach 迭代流中的数据
testFilter(list);
}
// 结果
原始数据:[abc, 123, ca]
过滤数据,筛选除字符串中包含a的字符串:[abc, ca]
四、测试sorted和limit
sorted 方法用于对流进行排序。
limit 方法用于获取指定数量的流。
下面筛选数组中最大的三个数:
public static void testSort(List<Integer> list){
List<Integer> squaresList = list.stream().sorted((v1,v2)->{
return v2-v1;
}).limit(3).collect(Collectors.toList());
System.out.println("筛选数组中最大的三个数:"+ squaresList);
}
public static void main(String[] args){
//初始化数据
List<Integer> list = Arrays.asList(1,11,5,7,2,9,9);
System.out.println("原始数据:" + list);
//测试 forEach 迭代流中的数据
testSort(list);
}
结果:
原始数据:[1, 11, 5, 7, 2, 9, 9]
筛选数组中最大的三个数:[11, 9, 9]
解释:先对数组按照从大到小排序,再使用limit限制流的数量。