stream()是jdk8的新特性,得到的是Stream(流)对象,使得可以将数组集合等数据使用类似迭代器的方式进行操作,使用流时,数据只能单次遍历,不能逆流。
1、stream特点
- stream的操作必须使用lambda作为参数
- stream没有内部存储,只是类似水流一样从数据源抓取数据
- 对数据源进行操作但不能改变数据源,而是得到一个新的stream,并可以组成集合数组等
- 消费性,stream只能被消费一次,消费以后就失效了,如果还需要消费,则必须重新生成stream,即同一个stream对象只能使用一次
2、Stream中的部分常用方法
collect()
将流输出为特定的格式,如数组、集合等,通常结合其他方法使用,比如filter()和map()等,将这些方法返回的新的流输出为特定格式
filter()
将流通过指定的方式过滤,得到所有返回为true的元素,组成一个新的stream
List<Integer> list = new ArrayList<>();
list.add(12);
list.add(18);
list.add(22);
list.add(30);
//i类似迭代器中的迭代变量,变量名任意取,这里的意思是过滤数字大于等于18的元素,组成一个新的集合
List<Integer> result = list.stream().filter(i -> i >= 18).collect(Collectors.toList());
System.out.println("result:" + result);//result:[18, 22, 30]
map()和flatMap()
map():将一个流元素按照一定规则转换为另一个元素,适用于1对1时
//这些user都是Users的对象,里面有id和name等属性
List<Users> list = Arrays.asList(user1, user2, user3, user4);
//这里的规则是拿取每个用户的name属性,这里转换成为了一个字符串,由collect方法连接成一个字符串类型的集合
List<String> names = list.stream().map(user -> user.getName()).collect(Collectors.toList());
System.out.println(names);//["张三", "李四", "王五", "赵六"]
flatMap():这里适用于1对多
//由多个Integer类型组成的集合组合而成一个大集合
List<List<Integer>> list = Arrays.asList(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
//由flatMap方法将list集合中每一个元素变成流从而组成一个大的流,并由collect方法连接起来
List<Integer> result = list.stream().flatMap(i -> i.stream()).collect(Collectors.toList());
System.out.println(result);//[1, 2, 3, 4, 5, 6]
forEach()
该方法传入一个lambda表达式,遍历流的每一个元素,让每个元素都执行lambda表达式
List<Users> list = Arrays.asList(user1, user2, user3, user4);
//jdk8以前:
for(u : list){
if(u.getAge() >= 18){
System.out.println(u.getName());
}
}
//jdk8:
list.stream().forEach(u -> {
if(u.getAge() >= 18){
System.out.println(u.getName());
}
});
reduce()
这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce。也有没有起始值的情况,这时会把 Stream 的前面两个元素组合起来,返回的是 Optional。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
//求list集合的元素之和, 有起始值,result = 10
int result = liststream().reduce(0, Integer::sum); //result = 15
// 求最小值,minValue = 1
int minValue = list.stream().reduce(Double.MAX_VALUE, Double::min);
// 求最大值,maxValue = 5
int maxValue = list.stream().reduce(Double.MAX_VALUE, Double::min);
// 求和,sumValue = 10, 无起始值,返回Optional,所以有get()方法
sumValue = list.stream().reduce(Integer::sum).get();