2017-06-20 36 views
2

我有一個LinkedList使用數據(author, date , LinkedList<Changes(lines, path)>)填充地圖<字符串,地圖<字符串,整數>>帶有流

現在我想用流來創建出這樣的Map< Filepath, Map< Author, changes >>

public Map<String, Map<String, Integer>> authorFragmentation(List<Commit> commits) { 

     return commits.stream() 
         .map(Commit::getChangesList) 
         .flatMap(changes -> changes.stream()) 
         .collect(Collectors.toMap(
           Changes::getPath, 
           Collectors.toMap(
           Commit::getAuthorName, 
           (changes) -> 1, 
           (oldValue, newValue) -> oldValue + 1))); 
} 

我嘗試它如此,但這並不奏效。 如何在流中創建此地圖並同時計數更改?

+1

,你的項目是'Changes',而不是'Commit'了。 –

+1

[Java8:HashMap 到HashMap 使用Stream/Map-Reduce/Collector]的可能重複(https://stackoverflow.com/questions/25903137/java8-hashmapx-y-to-hashmapx-z-using-stream- map-reduce-collector) –

回答

3

傑里米格蘭在他的評論中是完全正確的:在你的收藏家裏,它早已被遺忘,你從Commit物品流開始,所以你不能在那裏使用Commit::getAuthorName。我們面臨的挑戰是如何將作者姓名保留在一個你也能找到路徑的地方。一種解決方法是將兩者都放入新創建的字符串數組中(因爲兩者都是字符串)。

public Map<String, Map<String, Long>> authorFragmentation(List<Commit> commits) { 
    return commits.stream() 
      .flatMap(c -> c.getChangesList() 
        .stream() 
        .map((Changes ch) -> new String[] { c.getAuthorName(), ch.getPath() })) 
      .collect(Collectors.groupingBy(sa -> sa[1], 
        Collectors.groupingBy(sa -> sa[0], Collectors.counting()))); 
} 

Collectors.counting()堅持計數成Long,不Integer,所以我已經修改了你的返回類型。如果有必要,我肯定可以轉換爲Integer,但我會首先考慮是否可以與Long住在一起。

這不是最漂亮的流碼,我會等待,看看其他的建議上來。

的代碼被編譯,但因爲我沒有對你的類和你的數據,我還沒有試過運行它。如果有任何問題,請回復。

+1

我測試過了,它效果很好,謝謝! – Drextor

0

你的錯誤就在於map/flatMap叫「扔掉」的Commit。試圖收集時,您不知道哪個Commit a Change屬於。爲了保留這些信息,我建議建立一個小的輔助類(你可以使用一個簡單的對,雖然):

public class OneChange 
{ 
    private Commit commit; 
    private Change change; 

    public OneChange(Commit commit, Change change) 
    { 
     this.commit = commit; 
     this.change = change; 
    } 

    public String getAuthorName() { return commit.getAuthorName(); }; 
    public String getPath()  { return change.getPath(); }; 
    public Integer getLines()  { return change.getLines(); }; 
} 

然後,您可以flatMap來,通過路徑和作者,然後和它組向上線改變:

commits.stream() 
     .flatMap(commit -> commit.getChanges().stream().map(change -> new OneChange(commit, change))) 
     .collect(Collectors.groupingBy(OneChange::getPath, 
             Collectors.groupingBy(OneChange::getAuthorName, 
                  Collectors.summingInt(OneChange::getLines)))); 

如果你不想總結線,但只是算Changes,通過Collectors.counting()更換Collectors.summingInt(OneChange::getLines)。在你的第二個`toMap`

相關問題