填充地图<string,map <string,integer>&gt;与流

时间:2017-06-20 11:07:56

标签: java java-8 java-stream

我有一个包含数据( 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)));
}

我试一试,但这不起作用。 如何在包含Stream的Map中创建此Map并同时计算更改?

2 个答案:

答案 0 :(得分: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 :(得分:0)

你的错误是Commit号召“扔掉”Commit。尝试收集时,您不知道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.summingInt(OneChange::getLines)

如果您不想总结这些行,只计算Collectors.counting(),请将@Html.DropDownListFor(model => model.Product, new SelectList(Model.ProductsList, "Key", "Value"), "-- Product --", new { @class = "form-control" } ) 替换为@Html.DropDownListFor(model => model.Product, new SelectList(Model.ProductsList), "-- Product --", new { @class = "form-control" } )