2015-11-19 74 views
4

試圖學習java 8 GroupingBy國家我想篩選高於平均年齡(收集)的記錄(人)返回滿足此條件的人員列表。java 8 groupingBy,字段大於平均值的篩選記錄

所以SQL相當於是

SELECT * FROM PERSON, AVG(AGE) AS AVG_AGE 
GROUPBY COUNTRY 
WHERE AGE > AVG_AGE 

這是我嘗試到目前爲止只花了我半路上

personStream.collect(
      Collectors.groupingBy(
        p -> p.getCountry(), 
        Collectors.averagingInt(p -> p.getAge))) 

到目前爲止,只返回我與分類爲關鍵和地圖按國家平均年齡作爲價值。

Chan, Japan, 40 
Chong, Japan, 20 
Amy, Japan, 37 
James, UK, 25 
Abby, UK, 15, 
Jean, France 15 
Pierre, France, 50 

Average Japanese age = 32.33 
Average UK age = 20 
Average French age = 32.5 

ResultSet 
Chan, Japan, 40 
Chong, Japan, 20 
Amy, Japan, 37 
James, UK, 25 
Pierre, France, 50 

任何提示,將不勝感激

+2

我認爲你必須在列表中迭代兩次 - 一次計算每個國家的平均年齡(如你已經做的那樣),第二次應用使用第一次生成的地圖的過濾器確定一個人的年齡高於平均年齡的步驟。 – Eran

+1

在SQL中,您應該使用HAVING子句按結果過濾組。 –

+0

正如@Tagir Valeev所提到的那樣,當你引用你的條件中的聚合值時,你很可能想要'HAVING'而不是'WHERE',然而,wtf是'WHERE NAME> AVG_AGE'應該做的?比較一個姓氏與年齡⁈ – Holger

回答

6

您將無法一次完成該操作。 2次通過是必要的:第一次計算平均值,第二次過濾年齡大於平均值的人。

請注意,您所寫的SQL查詢不起作用for the same reason:您無法在WHERE子句內引用列別名。

您的代碼正確計算居住在同一個國家的人的平均年齡。因此,我們需要添加過濾初始persons列表的代碼。

Map<String, Double> map = 
     persons.stream().collect(
      groupingBy(
       p -> p.getCountry(), 
       averagingInt(p -> p.getAge()) 
      ) 
     ); 

persons.stream().filter(p -> p.getAge() > map.get(p.getCountry())).collect(toList()); 
+0

謝謝。這正是我需要的。 –

0

我想你可能需要.filter(P - > p.getAge()> averageAge)莫名其妙地收集這averageAge從地圖你現在得到。