[英]Java 8 Streams API HAVING clause equivalent in a GroupingBy?
我在Streams API
遇到了難以解決的問題。 好吧,根據我所知,在一次調用中它是可解決的,但並不優雅。 下面,以FeatureContentWeight
對象流FeatureContentWeight
,我想按功能和內容進行分組,並獲取每個功能和內容的最大權重 。 我從數值Map
在最后,因為我已經沒有必要維持一個Map
。 問題是,我只希望其中包含3個以上項目的組 。 因此,我希望已超過給定計數的功能,內容對的每個功能和內容的最大權重。 在SQL
這只是一個簡單的HAVING
子句。 在Streams API
這看起來並不瑣碎,但是我只在Streams API
了幾天。
任何想法表示贊賞。 下面是我的方法,
List<FeatureContentWeight> nearestNeighbors = neighborPostings
.stream()
.collect(
groupingBy(
p -> FeatureContent.Create(p.getFeatureId(), p.getContentId()),
collectingAndThen(maxBy(comparingDouble(FeatureContentWeight::getWeight)),Optional::get))).values();
從您的描述看來,您似乎要過濾作為分組結果的地圖。 因此,您可以對分組結果應用toMap
收集器,然后過濾其values()
以便僅保留長度為3或更大的值。 您可能還可以跳過地圖創建並使用partitioningBy
收集器,但這可能更尷尬。
最后,對於轉換地圖,我發現Guava的輔助函數(例如Maps.filterValues()
提供的語法比Java 8短且可讀性強(流語法對於列表而言是不錯的選擇,但對於地圖而言,有時會變得很糟糕)。 如果您使用的是Java 8,則可以在Guava中使用閉包,因此您可以編寫如下代碼:
Map<A,B> unfiltered = <Java 8 grouping>
return Maps.filterValues(unfiltered, list -> list.size() > 3);
如您所見,不幸的是,JDK的Stream
API中沒有流式GROUP BY
操作(即使有流式distinct()
操作)。 collect()
是一個終端操作,它將組和聚合收集到一個具體的Map
。
但是,如本文所述,其中顯示了Java 8 Streams中的SQL子句及其等效項 ,您可以重新流式傳輸Map.entrySet()
並對其執行進一步的操作。
應用於您的代碼(我在這里做一些假設):
Map<FeatureContentWeight, Double> nearestNeighbors = neighborPostings
.stream()
// GROUP BY featureId, contentId
.collect(
groupingBy(
p -> FeatureContent.Create(p.getFeatureId(), p.getContentId())
)
)
// HAVING count(*) >= 3
.entrySet()
.stream()
.filter(e -> e.getValue().size() >= 3)
// SELECT grp, MAX(weight)
.map(e -> e.getValue().stream().collect(
maxBy(comparingDouble(w -> w.getWeight))
));
resultMap.values().removeIf(lst -> lst.size() < 3)
只需從結果中刪除不需要的所有內容
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.