從簡單入手
Stream 作為 Java 8 的一大亮點拾徙,好比一個高級的迭代器(Iterator)即供,單向,不可往復扫茅,數(shù)據(jù)只能遍歷一次蹋嵌,遍歷過一次后即用盡了,就好比流水從面前流過葫隙,一去不復返栽烂。
我們可以利用stream對數(shù)據(jù)進行分組。示例如下:
List<String> items =
Arrays.asList("apple", "apple", "banana",
"apple", "orange", "banana", "papaya");
Map<String, Long> result =
items.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.counting()
)
);
System.out.println(result);
輸出如下:
{papaya=1, orange=1, banana=2, apple=3}
進階需求
在實際需求中,我們可能需要對一組對象進行分組愕鼓,而且分組的條件有多個钙态。比如對國家和產品類型進行雙重分組慧起,一種比較復雜的方法是先對產品類型進行分組菇晃,然后對每一個產品類型中的國家名進行分組求和。示例如下:
Map<String, List<item>> countMap = recordItems.stream().collect(Collectors.groupingBy(o -> o.getProductType()));
List<Record> records = new ArrayList<Record>;
countMap.keySet().forEach(productType -> {
Map<String, Long> countMap1 = countMap.get(productType).stream().collect(Collectors.groupingBy(o -> o.getCountry(), Collectors.counting()));
countMap1(key).stream().forEach(country -> {
Record record = new Record();
record.set("device_type", productType);
record.set("location", country;
record.set("count", countMap1(key).intValue());
records.add(record);
});
});
更好的解決方法
上面的方法在應對兩個字段的分組要求時蚓挤,還能應付的過來磺送,但如果字段超過兩個時,每增加一個字段灿意,就會多出很多代碼行估灿,顯然不太合理。更合理的方法是缤剧,增加一個 getKey()方法馅袁,返回多個字段組成的唯一key,比如通過下劃線連接等等荒辕。示例如下:
// 分組統(tǒng)計
Map<String, Long> countMap = records.stream().collect(Collectors.groupingBy(o -> o.getProductType() + "_" + o.getCountry(), Collectors.counting()));
List<Record> countRecords = countMap.keySet().stream().map(key -> {
String[] temp = key.split("_");
String productType = temp[0];
String country = temp[1];
Record record = new Record();
record.set("device_type", productType);
record.set("location", country;
record.set("count", countMap.get(key).intValue());
return record;
}).collect(Collectors.toList());
參考資料
文章標題:Java8 stream 中利用 groupingBy 進行多字段分組
文章作者:Ciel Ni
文章鏈接:http://www.cielni.com/2018/07/14/java-stream-groupingby/
有問題或建議歡迎與我聯(lián)系討論汗销,轉載或引用希望標明出處,感激不盡抵窒!