一,Stream流
- 概述:是用来代替遍历容器行为,对容器中的数据进行处理的一种工具。stream不能承载任何数据,只对容器的数据进行维护处理。
- 举例:stream 流类似工厂的生产线 容器相当于产品 数据是在容器,每次变化变化的是数据,容器发生变化。【Stream相当于是流水线 他的方法属于一道道的工序 】
-
Stream类型数据的获取【把容器放到Stream(流水线)上】
- Collection 的获取 stream 对象的方式:
- 集合对象.stream(): 把集合对象转换为stream流对象。
- Map的获取stream对象:不能直接获取Stream对象
- 把双列集合转变成单列集合,采用单列集合转换 stream 流方式操作
- 双列集合转换为单列集合的方式:keySet()、entrySet()、values()
- 数组的获取stream对象
- 采用 Stream 接口中的静态方法:Stream.of(数组对象)
代码示例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.stream.Stream;
public class Demo_Stream01 {
public static void main(String[] args) {
//list 单列集合
ArrayList<Object> list = new ArrayList<>();
//将list 集合放到流对象中去
Stream<Object> list_stream = list.stream();
list.add("春天");
list.add("夏天");
list.add("秋天");
list.add("冬天");
//数组
int[] arr = {1,2,3,4,5,6};
Stream<int []> arr_stream = Stream.of(arr);
//map双列集合
HashMap<Object, Object> map = new HashMap<>();
Set<Object> set = map.keySet();//将双列集合变为单列集合
Stream<Object> set_stream = set.stream();
//终结方法
//arr_stream.forEach((s)->{System.out.println(Arrays.toString(s));}); //[1, 2, 3, 4, 5, 6]
//list_stream.forEach(System.out::println); //春天 夏天 秋天 冬天 ---- 方法引用
long len = arr_stream.count();
System.out.println(len); //数组看作是整体对象为1 输出为1,没有tostring方法无法深入到数组内部所有看作一个长度
long len2 = list_stream.count();
System.out.println(len2); //4 4个字符串,四个内容
}
}
-
Stream中的常用方法
- 常用方法:
终结方法:就是stream调用该方法后返回的数据类型不是Stream对象的方法
- foreach():打印 stream 中容器数据
- count():获取 stream 中数据个数的
- 如何把生产线上处理好的数据拿下来存放到对应的容器中:
- toArray():把 stream 处理后的数据取出到数组中
- collect(Collector c):把 stream 中的数据取出放到集合中
代码示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Demo_Stream01 {
public static void main(String[] args) {
//首先使用stream流
ArrayList<String > list = new ArrayList<>();
list.add("春天");
list.add("夏天");
list.add("秋天");
list.add("冬天");
//将这些内容放到stream流里面
Stream<String > stream = list.stream();
//把stream的数据拿下来 放到对应的容器中
// Object[] arr = stream.toArray();
//数组是不能直接强转的,只能遍历 对里面的数据一个一个的单独强转
// System.out.println(Arrays.toString(arr)); //[春天, 夏天, 秋天, 冬天]
//参数需要的是collection的对象 如何获取对象? 使用一个工具类
// List<String >list2 = stream.collect(Collectors.toList()); //把stream中的数据添加到一个list集合中
// System.out.println(list2); //[春天, 夏天, 秋天, 冬天]
Set<String >set = stream.collect(Collectors.toSet()); ////把stream中的数据添加到一个set集合中
System.out.println(set); //[夏天, 秋天, 冬天, 春天]
}
}
延迟方法:就是stream调用该方法后返回的数据类型还是stream对象的方法
- filter(Predicate p):过滤容器数据的
- limit(long num):截取 stream 操作数据的前 num 个元素
- skip(long num):跳过开头的前 num 个元素
- map(Function f):把 stream 中的数据转换成其他数据
- concat(Stream stream):拼接两个 stream 成为一个 stream
- 在 stream 中除了终结方法就是延迟方法。
- 总结:stream 流对象不能二次使用,用完就关闭了【用完就改变了】。
代码示例
import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo_Stream02 {
public static void main(String[] args) {
// 首先使用stream流
ArrayList<String> list = new ArrayList<>();
list.add("春天");
list.add("夏天");
list.add("秋天");
list.add("冬天");
list.add("春分分");
list.add("夏至至");
list.add("中秋秋");
list.add("冬至至");
list.add("端午");
list.add("新年");
Stream<String> stream = list.stream();
// 延迟方法
// (s)->{return s.length()==2;}传递一个筛选逻辑
Stream<String> ft = stream.filter((s) -> {return s.length() == 2;});
// ft.forEach(System.out::println);//调用foreach 方法打印内部的内容,字符串为2个字的全部筛选出来了6个
// 获取前4个字符串
Stream<String> lm = ft.limit(4);
// System.out.println(lm); //java.util.stream.SliceOps$1@3b9a45b3 获取的是流的对象的地址值
// stream流里面没有承载数据的能力只有处理数据的能力,流里面不存放任何东西
// lm.forEach(System.out::println); //春天 夏天 秋天 冬天
Stream<String> sk = lm.skip(1); // 跳过第一个字符串
// sk.forEach(System.out::println); //夏天 秋天 冬天
/*
* Stream<ArrayList>map_Stream = sk.map((s)->{
ArrayList list1= newArrayList<>();
list1.add(s);
return list1;});
* map_Stream.forEach(System.out::println); //得到3个集合[夏天] [秋天]
* [冬天],把string类型的变成了list类型的了
*/
// 流不能二次调用,一个流只能用一次
// 创建新的流
Stream<String> stream1 = list.stream();
// 拼接两个新流stream1和sk流
Stream<String> concat_Stream = Stream.concat(stream1, sk);
concat_Stream.forEach(System.out::println); // 打印stream1 和sk 流里面的所有的内容
}
}
练习
- 有两个字符串数组,分别存储队伍中的多个成员姓名,使用Stream方式,进行以下操作:
- 第一个队伍只要名字为3个字的成员姓名【filter】
- 第一个队伍只要筛选之后的前三个人【limit】
- 第二个队伍只要姓张的【filter】
- 第二个队伍筛选之后不要前两个人【skip】
- 将两个队伍合并成一个队伍【concat】
- 合并之后的队伍中的所有人名字变为Person(自定义类型)对象,【map 自定义Person类】
- 将person对象存储到一个List集合中【collect】
- 队伍1:宫本武藏、宋公明、苏有朋、石头人、时传祥、李耳、庄子、洪七公
- 队伍2:帕瓦罗蒂、张三疯、赵薇薇、张自忠、孛儿只斤铁木真、张天爱、张翠花
代码示例
//定义一个Person类
public class Person {
private String name;
public Person(String name) {
super();
this.name = name;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [name=" + name + "]";
}
}
// 定义一个测试类
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Stream_Test {
public static void main(String[] args) {
String[] arr1 = "宫本武藏,宋公明,苏有朋,石头人,时传祥,李耳,庄子,洪七公".split(",");
String[] arr2 = "帕瓦罗蒂,张三疯,赵薇薇,张自忠,孛儿只斤铁木真,张天爱,张翠花".split(",");
//将字符串存入stream流中
Stream<String> stream1 = Stream.of(arr1);
Stream<String> stream2 = Stream.of(arr2);
//1、第一个队伍只要名字为3个字的成员姓名【filter】
//2、第一个队伍只要筛选之后的前三个人【limit】
Stream<String > limit1 = stream1.filter((s)->{return s.length() == 3;}).limit(3);
//3、第二个队伍只要姓张的【filter】
//4、第二个队伍筛选之后不要前两个人【skip】
Stream<String> skip1= stream2.filter((s)->{return s.startsWith("张");}).skip(2);
//5、将两个队伍合并成一个队伍【concat】
Stream<String> concat = Stream.concat(limit1,skip1);
//6、合并之后的队伍中的所有人名字变为Person(自定义类型)对象,【map 自定义Person类】
//Stream<Person> map =concat.map((s)->{return new Person(s);}); //把s封装到person里面
Stream<Person> map1 = concat.map(Person :: new); //简写--构造方法 类名::new
//7、将person对象存储到一个List 集合中【collect】
List<Person> list = map1.collect(Collectors.toList());
System.out.println(list);
//结果:[Person [name=宋公明], Person [name=苏有朋], Person [name=石头人], Person [name=张天爱], Person [name=张翠花]]
}
}