Java集合的流Stream操作(快速筛查,统一处理)
说明
Java中的集合流操作需要java 8的特性支持。需要对Lambda
表达式有所了解
主要作用:
- 快速筛查集合元素
- 统一对集合元素处理
说白了就是原来的要大量循环的操作可以使用流操作快速完成
假设条件
之后的代码演示将于以下的假设条件来模拟表示
存在Message
类
public class Message{
String value;
int code;
}
存在ShortMessage
类
public class ShortMessage{
String value;
}
Tools
类中存在方法
public static ShortMessage convert(Message msg){
return new ShortMessage(msg.getValue);
}
存在一个数组,里面存在大量已经实例化的Message对象
List<Message> messageList;
省略get、set及构造函数无营养代码
filter操作
作用:快速筛查,过滤元素留下符合要求的元素生成一个新的流
假设存在
//快速筛查出value属性包含‘bug’的message对象
messageList = messageList.parallelStream()//转为并行流,多线程
.filter(msg -> msg.getValue().contains("bug"))//筛查
.collect(Collectors.toList());//流转回list
msg 相当于循环messageList中的每一个Message实例对象的临时引用
filter
返回的还是一个stream,所以是可以一直链式调用操作的,比如一直.filter.filter过滤
filter
操作接受的是一个Predicate
逻辑表达式,既结果是一个布尔结果,为true的保留
map操作
作用:统一处理
map操作理解起来有点复杂,请看以下例子
假设我们需要将messageList
里面的所有实例转为ShortMessage
对象
一般处理
List<ShortMessage> shorts = new ArrayList<>();
for(Message msg:messageList){
shorts.add(Tools.convert(msg));
}
流map处理方式
List<ShortMessage> shots = messageList.parallelStream()
.map(Tools::convert)
.collect(Collectors.toList());
所以说,map操作可以了解为需要对一个流中的元素统一处理时的操作,会将流中的每一个元素循环调用方法作为参数传递进去
注意map中的方法多次执行返回也是一个流,而这个流的存储的元素的类型是会变化的,具体看调用方法的返回类型
map返回的流也是可以继续链式调用的
当然也可以这样,相信下面的代码不需要我解释
List<ShortMessage> shorts = messageList.parallelStream()
.filter(msg -> msg.getValue().contains("bug"))
.map(Tools::convert)
.collect(Collectors.toList());
假设我们需要将所有的Message对象的code
加100
记住,流操作里面的只要是个Lambda表达式就可以
messageList = messageList.parallelStream()
.map(msg -> msg.setCode(msg.getCode()+100))
.collect(Collectors.toList());
flatMap操作
这个说明一下,以免以后忘记
map
操作可以看到可以了解为一对一映射操作,每输入一个元素,则按map
中的方法规则处理转换为另外一个元素,但有的时候是一对多操作的;
如果从字面意思上理解,就是map
的扁平化操作一般用在复合数组上面,flatMap
会将流中的每一个元素再转为流操作
List<List<Message>> list;
//如果
list.parallelStream().flatMap(child -> child.stream());
//那么A表示list中的子集合的流,-> 后面必须产生一个新的流,最终;flatMap会产生一个合并出来的大的流
简单例子说明
假设存在
public class data{
int x;
int y;
}
修改Message类
public class Message{
String value;
int code;
Data[] datas;
/**
*[]数组和List是两回事,这里这个方法只是演示如果data是List类型情况下
*/
public List<Data> getDataArray(){
return Arrays.asList(data.clone());
}
}
测试数据
Message m1 = new Message("message 1", new Data[]{new Data(3, 2), new Data(3, 2), new Data(3, 2)});
Message m2 = new Message("message 2",new Data[]{new Data(4, 2), new Data(6, 2), new Data(3, 2)});
Message m3 = new Message("message 3",new Data[]{new Data(5, 2), new Data(4, 2), new Data(4, 2)});
Message m4 = new Message("message 4",new Data[]{new Data(6, 2), new Data(3, 2), new Data(3, 2)});
Message m5 = new Message("message 5",new Data[]{new Data(7, 2), new Data(2, 2), new Data(7, 2)});
Message m6 = new Message("message 6",new Data[]{new Data(8, 2), new Data(45, 2), new Data(3, 2)});
List<Message> messageList = Arrays.asList(m1, m2, m3, m4, m5, m6);
现在就是说,有一个messageList
保存多个Message
对象,每个Message
对象操作一个Data
类型数组
一、找出所有x
值为3的Data
对象
List<Data> collect = messageList.parallelStream()
.map(Message::getDatas)//把data取出来,创建一个全是data[]的流
.flatMap(Arrays::stream)//转为流,注意会合并,创建一个全是data的流
.filter(data -> data.getX() == 3)//筛查
.collect(Collectors.toList());
换种写法,如果是list
操作会更简单
List<Data> collect1 = messageList.parallelStream().flatMap(msg -> msg.getDataArray().stream()).filter(data -> data.getX() > 3).collect(Collectors.toList());
二、获取所有的X
的值
List<Integer> integerList = messageList.parallelStream().flatMap(ss -> ss.getDataArray().stream()).map(Data::getX).collect(Collectors.toList());
剩下的就不一一举例了,可以发现flatMap
其实可以理解为合并处理