Java集合的流Stream操作(快速筛查,统一处理)

说明

Java中的集合流操作需要java 8的特性支持。需要对Lambda表达式有所了解

主要作用:

  1. 快速筛查集合元素
  2. 统一对集合元素处理

说白了就是原来的要大量循环的操作可以使用流操作快速完成

假设条件

之后的代码演示将于以下的假设条件来模拟表示

存在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其实可以理解为合并处理

posted @ 2020-10-31 00:41  南城之南  阅读(1518)  评论(0编辑  收藏  举报