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