什么是Stream?
Stream
将要处理的元素集合看作一种流,在流的过程中,借助Stream API
对流中的元素进行操作,比如:筛选、排序、聚合等
Stream流的作用:
结合了Lambda表达式,简化集合、数组的操作
Stream流的使用步骤:
①先得到一条Stream流(流水线),并把数据放上去
②利用Stream流中的API进行各种操作:比如
中间方法:(过滤、转换) 方法调用完毕之后,还可以调用其他方法
终结方法:(统计、打印) 最后一步,调用完毕之后,不能调用其它方法
总的来说三步:
1.先得到一条Stream流(流水线),并把数据放上去
2.使用中间方法对流水线上的数据进行操作
3.使用终结方法对流水线上的数据进行操作
让我们来一步步介绍
①得到一条Stream流(流水线),并把数据放上去
获取方式 | 方法名 | 说明 |
单列集合 | default Stream<E>stream() | Collection中的默认方法 |
双列集合 | 无 | 无法直接使用Stream流 |
数组 | public static<T>Stream<T>stream(T[]array) | Arrays工具类中的静态方法 |
一堆零散数据 | public static<T>Stream<T>of(T...values) | Stream接口中的静态方法 |
方法演示:
package StreamDemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class demo1 {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"a","b","c","d","e");
Stream<String> stream = list.stream();//ctrl+v自动生成左边
list.stream().forEach(s->{
System.out.println(s);
});
//双列集合获取Stream流时必须利用keySet()或者entrySet()方法获取单列集合,然后再获取流
HashMap<String,Integer> hm=new HashMap<>();
hm.put("aaa",111);
hm.put("bbb",222);
hm.keySet().stream().forEach(s->System.out.println(s));
hm.entrySet().stream().forEach(s->System.out.println(s.getKey()));
int []arr={1,2,3,4,5,6};
Arrays.stream(arr).forEach(s->System.out.println(s));
//Stream接口中静态方法of的细节
//方法形参是一个可变参数,可以传递一堆零散数据,也可以传递数组
//但是数组必须是引用数据类型,如果传递基本数据类型,会把整个数组当作一个元素,放入Stream中
Stream.of(arr).forEach(s->System.out.println(s));
String []arr2={"a","b","c"};
Stream.of(arr2).forEach(s->System.out.println(s));
}
}
运行结果:
aaa
bbb
aaa
bbb
1
2
3
4
5
6
[I@7699a589
a
b
c
②使用中间方法对流水线上的数据进行操作
名称 | 说明 |
Stream<T>filter(Predicate<?super T>) predicate | 过滤 |
Stream<T>limit(long maxSize) | 获取前几个元素 |
Stream<T>skip(long n) | 跳过前几个元素 |
Stream<T>distinct | 元素去重 |
static<T>Stream<T>concat(Stream a,Stream b) | 合并a和b为一个流 |
static<R>map(Function<T,R> mapper) | 转换流中的数据类型 |
注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
注意2:修改Stream流中数据,不会影响原来的集合或者数组中的数据
代码演示:
package StreamDemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class demo3 {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠三","张良","王二麻子","谢广坤");
//1.filter 过滤,把张开头的留下,其余过滤不变
System.out.print("filter:把张开头的留下");
Stream<String> stream = list.stream();
stream.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
//如果为true,则把当前数据的留下
//如果为false,则把当前数据舍弃
return s.startsWith("张");
}
}).forEach(s->System.out.print(s+" "));
System.out.println();
//把姓张且长度为3进行过滤
//以下的方法会报错 stream has already been operated upon or closed :正好验证了注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
//stream.filter(s->s.length()==3).forEach(s->System.out.println(s));
//那么我们试试链式编程
System.out.print("filter链式编程:");
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s->System.out.print(s+" "));
System.out.println();
System.out.print("集合里面的数据:");
System.out.println(list);//注意2:修改Stream流中数据,不会影响原来的集合或者数组中的数据
//limit 获取前三个元素
System.out.print("limit 获取前三个元素");
list.stream().limit(3).forEach(s->System.out.print(s+" "));
System.out.println();
System.out.print("skip 跳过前几个元素:");
list.stream().skip(3).forEach(s->System.out.print(s+" "));
System.out.println();
System.out.print("去重之后:");
ArrayList<String> list2=new ArrayList();
Collections.addAll(list2,"张无忌","张无忌","张无忌","张无忌","张无忌","张无忌","张无忌","王二麻子","谢广坤");
//distinct 去重 看源码可以知道distinct底层时hashSet
list2.stream().distinct().forEach(s->System.out.print(s+" "));
//concat 合并两个流
System.out.println("concat 合并两个流:");
Stream.concat(list.stream(),list2.stream()).forEach(s->System.out.print(s+" "));
System.out.println();
//map转换流中的数据类型
System.out.print("stream.map转换数据类型 获取集合中的年龄:");
ArrayList<String> list3=new ArrayList<>();
Collections.addAll(list3,"张无忌-13","周芷若-14","赵敏-15","张强-16","张三丰-15");
list3.stream().map(new Function<String, Integer>() {//函数式接口
@Override
public Integer apply(String s) {
String []arr=s.split("-");
int x=Integer.parseInt(arr[1]);
return x;
}
}).forEach(s->System.out.print(s+" "));
System.out.println();
}
}
运行结果:
filter:把张开头的留下张无忌 张强 张三丰 张翠三 张良
filter链式编程:张无忌 张三丰 张翠三
集合里面的数据:[张无忌, 周芷若, 赵敏, 张强, 张三丰, 张翠三, 张良, 王二麻子, 谢广坤]
limit 获取前三个元素张无忌 周芷若 赵敏
skip 跳过前几个元素:张强 张三丰 张翠三 张良 王二麻子 谢广坤
去重之后:张无忌 王二麻子 谢广坤 concat 合并两个流:
张无忌 周芷若 赵敏 张强 张三丰 张翠三 张良 王二麻子 谢广坤 张无忌 张无忌 张无忌 张无忌 张无忌 张无忌 张无忌 王二麻子 谢广坤
stream.map转换数据类型 获取集合中的年龄:
13 14 15 16 15
③Stream流中的终结方法
名称 | 说明 |
void forEach(Consumer action) | 遍历 |
long count() | 统计 |
toArray() | 收集流中的数据,放到数组中 |
collect(Collector collector) | 收集流中的数据,放到集合中 |
package StreamDemo;
import java.util.*;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class demo4 {
public static void main(String[] args) {
System.out.println("forEach获取流中的每一个数据");
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠三","张良","王二麻子","谢广坤");
list.stream().forEach(s->System.out.print(s+" "));
System.out.println();
System.out.println("count统计流中的数据个数:");
System.out.print(list.stream().count());
System.out.println();
System.out.println("收集流中的数据,放到数组里");
//apply的形参:流中数据的个数
String []arr=list.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
System.out.print(Arrays.toString(arr));
System.out.println();
ArrayList<String> list3=new ArrayList<>();
Collections.addAll(list3,"张无忌-13-男","周芷若-14-女","赵敏-15-女","张强-16-男","张三丰-15-男","张三丰-15-男");
System.out.println("collect方法收集流中的数据并把其放入集合中");
//获取到所有的男性,并把其放到集合中
List<String> list4=list3.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.split("-")[2].equals("男");
}
}).collect(Collectors.toList());
System.out.println("收集到list集合中:"+list4);
//放入Set集合
Set<String> set=list3.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.split("-")[2].equals("男");
}
}).collect(Collectors.toSet());
System.out.println("收集到set集合中:"+set);
//收集到map集合中 键姓名 值男性
/*
toMap:
参数一表示键的生成规则
参数二表示值的生成规则
参数一:
Function泛型一:表示流中每一个数据的类型
泛型二:表示map集合中键的数据类型
方法apply形参:依次表示流里面的每一个数据
方法体:生成键的代码
返回值:已经生成的键
参数二:
Function泛型一:表示流中每一个数据的类型
泛型二:表示map集合中值的数据类型
方法apply形参:依次表示流里面的每一个数据
方法体:生成值的代码
返回值:已经生成的值
*/
ArrayList<String> list5=new ArrayList<>();
Collections.addAll(list5,"张无忌-13-男","周芷若-14-女","赵敏-15-女","张强-16-男","张三丰-15-男");
//注意点
//键不能重复,不然会报错
Map<String,String> map=list5.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.split("-")[2].equals("男");
}
}).collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
}, new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[2];
}
}));//写键的规则和值的规则
System.out.println("收集到,map集合中:"+map);
}
}
运行结果:
forEach获取流中的每一个数据
张无忌 周芷若 赵敏 张强 张三丰 张翠三 张良 王二麻子 谢广坤
count统计流中的数据个数:
9
收集流中的数据,放到数组里
[张无忌, 周芷若, 赵敏, 张强, 张三丰, 张翠三, 张良, 王二麻子, 谢广坤]
collect方法收集流中的数据并把其放入集合中
收集到list集合中:[张无忌-13-男, 张强-16-男, 张三丰-15-男, 张三丰-15-男]
收集到set集合中:[张强-16-男, 张三丰-15-男, 张无忌-13-男]
收集到,map集合中:{张强=男, 张三丰=男, 张无忌=男}
内容来自Stream流-02-Stream流的思想和获取Stream流_哔哩哔哩_bilibili
标签:java,stream,Stream,System,张无忌,-----,println,out From: https://blog.csdn.net/qq_44766305/article/details/142338561