[英]How to groupBy and Collect with Java 8?
我有一個元素列表,將其稱為“關鍵字”,如下所示:
public class Keyword {
Long id;
String name;
String owner;
Date createdTime;
Double price;
Date metricDay;
Long position;
}
問題是每一天都有一個關鍵字。 例如:
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.1", metricDay="11/11/1999", position=109}
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.3", metricDay="12/11/1999", position=108}
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.2", metricDay="13/11/1999", position=99}
Keyword{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", price="0.6", metricDay="13/11/1999", position=5}
Keyword{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", price="0.1", metricDay="14/11/1999", position=4}
Keyword{id=3, name="kw3", owner="Josh", createdTime="13/12/1992", price="0.1", metricDay="13/11/1999", position=8}
然后,從該列表中,我想創建一個新列表,將來自所有不同日期的所有指標合並到一個列表中。 首先,我創建了一個像這樣的類:
public class KeywordMetric {
Double price;
Date metricDay;
Long position;
}
我要存檔的是從第一個列表轉到這樣的結構:
public class KeywordMeged {
Long id;
String name;
String owner;
List<KeywordMetric> metricList;
}
我期望的示例:
KeywordMerged{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", metricList=[KeywordMetric{price=0.1,metricDay="11/11/1999",position=109},KeywordMetric{price=0.3,metricDay="12/11/1999",position=108},KeywordMetric{price=0.2,metricDay="13/11/1999",position=99}]
KeywordMerged{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", metricList=[KeywordMetric{price=0.6,metricDay="13/11/1999",position=5},KeywordMetric{price=0.1,metricDay="14/11/1999",position=4}]
KeywordMerged{id=3, name="kw3", owner="Josh", createdTime="13/12/1992", metricList=[KeywordMetric{price=0.1,metricDay="13/11/1999",position=8}]
我知道如何使用許多循環和可變變量來執行此操作,但是我不知道如何使用流和lambda操作來執行此操作。 我可以使用ID將所有相關關鍵字分組:
Map<Long, List<Keyword>> kwL = kwList.stream()
.collect(groupingBy(Keyword::getId))
而且我知道使用.forEach()
可以遍歷該Map,但無法弄清楚如何使流的collect()
方法從List傳遞到KeywordMerged。
您可以嘗試使用Collectors.toMap(...)
。 哪里:
Keyword::getId
是一個鍵映射器函數。
KeywordMerged.from(...)
執行轉換: Keyword => KeywordMerged
(left, right) -> { .. }
組合具有相同ID的實體的指標。
Collection<KeywordMerged> result = keywords.stream()
.collect(Collectors.toMap(
Keyword::getId,
k -> KeywordMerged.from(k), // you can replace this lambda with a method reference
(left, right) -> {
left.getMetricList().addAll(right.getMetricList());
return left;
}))
.values();
轉換方法可能看起來像這樣:
public class KeywordMerged {
public static KeywordMerged from(Keyword k) {
KeywordMetric metric = new KeywordMetric();
metric.setPrice(k.getPrice());
metric.setMetricDay(k.getMetricDay());
metric.setPosition(k.getPosition());
KeywordMerged merged = new KeywordMerged();
merged.setId(k.getId());
merged.setName(k.getName());
merged.setOwner(k.getOwner());
merged.setMetricList(new ArrayList<>(Arrays.asList(metric)));
return merged;
}
}
我認為您已經有了基本的想法。 因此,請根據您的需求進行重構...
略有不同的方法。 首先,您收集按ID分組的關鍵字地圖:
Map<Integer, List<Keyword>> groupedData = keywords.stream()
.collect(Collectors.groupingBy(k -> k.getId()));
進一步,您將地圖轉換為所需格式的列表:
List<KeywordMerged> finalData = groupedData.entrySet().stream()
.map(k -> new KeywordMerged(k.getValue().get(0).getId(),
k.getValue().stream()
.map(v -> new KeywordMetric(v.getMetricDay(), v.getPrice(), getPosition()))
.collect(Collectors.toList())))
.collect(Collectors.toList());
這將對分組數據起作用,但是轉換地圖將創建KeywordMerged
對象,該對象將作為參數接收ID(您可以自己進一步擴展),並轉換為先前按ID數據分組的List<KeywordMetric>
。
編輯:我相信與一些方法的提取,您可以使其看起來更好:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.