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其實可以理解為合並處理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM