2017-08-09 38 views
1

平均我有對象的列表的Android流從地圖

class Result { 
    private String name; 
    private Map<String, Double> map; 

    // getters, constructor etc 
} 

我想通過名稱組它,並進行雙值的平均值的地圖每個鍵。列表中的每個對象都具有相同鍵的地圖。

我開始按名稱

Map <String, List<Result>> grouppedByName = Stream.of(results) 
     .collect(Collectors.groupingBy(Result::getName)); 

分組不知何去何從除了定期循環。

實施例的數據:

INPUT: 

name = "Name 1" 
map: 
KEY1, 10 
KEY2, 1 

name = "Name 1" 
map: 
KEY1, 20 
KEY2, 7 

name = "Name 2" 
map: 
KEY1, 2 
KEY2, 3 
-------------- 
OUTPUT: 

name = "Name 1" 
map: 
KEY1, 15       (10+20)/2 = 15 
KEY2, 4       (1+7)/2 = 4 

name = "Name 2" 
map: 
KEY1, 2 
KEY2, 3 
+0

你應該更具體的,顯示你的輸入,並顯示預期的輸出 – mac229

+0

我添加了一個示例數據 – kkkkk

回答

1

groupingBy方法將產生Map<String, List<Result>>。我們需要一種方法來這個地圖的List<Result>值轉化爲更有用的東西:

Map<String, Double> mapMerger(final List<Result> results) { 
    return results.stream() 
      .map(Result::getMap) 
      .map(Map::entrySet) 
      .flatMap(Set::stream) 
      .collect(groupingBy(Entry::getKey, averagingDouble(Entry::getValue))); 
} 

這將提取所有結果所有的地圖Entry<String, Double>類型的所有條目。它會將這些條目彙總到從每個鍵到該鍵的所有值的平均值的映射中。

我們可以通過創建從原始地圖(grouppedByName在你的問題)流應用此新方法:

Map<String, Map<String, Double>> averagedByName = results.stream() 
     .collect(groupingBy(Result::getName)) 
     .entrySet().stream() 
     .collect(toMap(Entry::getKey, e -> mapMerger(e.getValue()))); 

的你應該得到15如果你這樣做:

double avg = averagedByName.get("Name 1").get("KEY1");