Stream流
引例
需求:按照下面要求完成集合的创建和遍历
创建一个集合,存储多个字符串元素
1. 把所有以“曹”开头的元素存储到新集合中
2. 把曹开头,长度为3的元素存储到新集合中
List<String> list = List.of("曹操", "曹孟德", "曹子恒", "曹子建", "司马懿", "司马师", "司马昭", "曹丕");
// 1. 把所有以“曹”开头的元素存储到新集合中
List<String> list1 = new ArrayList<>();
for (String s : list) {
if(s.startsWith("曹")){
list1.add(s);
}
}
System.out.println(list1);
// 2. 把曹开头,长度为3的元素存储到新集合中
List<String> list2 = new ArrayList<>();
for (String s : list1) {
if(s.length() == 3){
list2.add(s);
}
}
System.out.println(list2);
输出结果:
[曹操, 曹孟德, 曹子恒, 曹子建, 曹丕]
[曹孟德, 曹子恒, 曹子建]
上面太麻烦了
用Stream流只需要一行代码:
list.stream().filter(name -> name.startsWith("曹")).filter(name -> name.length() == 3).forEach(name -> System.out.println(name));
- stream流的作用:结合Lamada表达式,简化集合、数组的操作
- 使用步骤:
-
先得到一条stream流,并把数据放上去
获取方式 方法名 说明 单列集合 default Stream<E> stream() Collection中的默认方法 双列集合 无 无法直接使用Stream流,需要通过keySet()或entrySet()转换成单列集合 数组 public static<T> Stream stream(T[] array) Arrays工具类中的静态方法 一堆零散数据 public static<T> Stream of(T…values) Stream接口中的静态方法 -
利用stream流中的API进行各种操作:(过滤,转换,统计,打印等等)
- 中间方法:过滤、转换。方法调用完毕之后还可以调用其他方法
- 终结方法:统计、打印。最后一步,调用完毕之后不能调用其他方法。
-
使用中间方法对流水线上的数据进行操作
-
使用终结方法对流水线上的数据进行操作
-
//单列集合Stream流
List<String> list = List.of("aa", "bb", "cc", "dd");
list.stream().forEach(s -> System.out.println(s));
//双列集合Stream流
Map<String, String> map = Map.of("aa", "11", "bb", "22", "cc", "33");
map.entrySet().stream().forEach(m -> System.out.println(m));
//数组Stream流
int[] arr = {1,2,3,4,5};
Arrays.stream(arr).forEach(a -> System.out.println(a));
//零散数据Stream流
Stream.of(11,12,13,14,15).forEach(s -> System.out.println(s));
注意:Stream接口中静态方法of的细节:方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组,但数组必须是引用数据类型的,如果传递基本数据类型,会把整个数组当做一个元素传到Steam流中
int[] arr1 = {1,2,3,4,5};
String[] arr2 = {"a", "b", "c", "d", "e"};
Stream.of(arr1).forEach(s -> System.out.println(s)); //输出[I@7699a589
Stream.of(arr2).forEach(s -> System.out.println(s)); //输出a b c d e
-
Stream流的终结方法
名称 说明 void forEach(Consumer action) 遍历 long count() 统计 toArray() 收集流中的数据,放到数组中 collect(Collector collrctor) 收集流中的数据,放到集合中 - forEach 返回值是void,因此是终结方法,不能再在后面调用函数
-
Consumer的泛型:表示流中数据的类型
-
accept方法得形态integer:依次表示流里面的每一个数据
-
方法体:对每一个数据要做的操作(打印)
List<Integer> list = List.of(1,2,3,4,5); list.stream().forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } });
-
long 返回值是long类型的整数,因此是终结方法
long c = list.stream().count(); System.out.println(c);
-
toArray()
-
空参:返回值是object类型
System.out.println("---------------------"); Object[] arr1 = list.stream().toArray(); System.out.println(Arrays.toString(arr1)); // //IntFunction的泛型:具体类型的数组 //apply的形态:流中数据的个数,要和数组长度保持一致 //apply函数返回值:具体类型的数组 //toArray方法的参数的作用:负责创建一个指定类型的数组 //方法底层会依次得到流里面每一个数据,并把数据放到数组中 //方法返回值:装着流里面所有数组的数组 String[] arr = list.stream().toArray(new IntFunction<String[]>() { @Override public String[] apply(int value) { return new String[0]; } }); //简化成Lamada表达式形式: list.stream().toArray(value -> new String[value]);
-
有参:返回值是任意类型
toArray方法的参数的作用:负责创建一个指定类型的数组
方法底层会依次得到流里面每一个数据,并把数据放到数组中
方法返回值:装着流里面所有数组的数组//IntFunction的泛型:具体类型的数组 //apply的形态:流中数据的个数,要和数组长度保持一致 //apply函数返回值:具体类型的数组 //toArray方法的参数的作用:负责创建一个指定类型的数组 //方法底层会依次得到流里面每一个数据,并把数据放到数组中 //方法返回值:装着流里面所有数组的数组 String[] arr = list.stream().toArray(new IntFunction<String[]>() { @Override public String[] apply(int value) { return new String[0]; } }); //简化成Lamada表达式形式: list.stream().toArray(value -> new String[value]);
- collect