用流填充地图<字符串,地图<字符串,整数>>



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

我试过了,但这不起作用。如何在带有流的地图中创建此地图并同时计算更改?

杰里米·格兰德(Jeremy Grand(在他的评论中是完全正确的:在您的收藏家中,人们早已忘记您是从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.

这不是最漂亮的流代码,我会等着看是否有其他建议。

代码已编译,但由于我既没有您的类也没有您的数据,因此我没有尝试运行它。如果有任何问题,请还原。

你的错误是map/flatMap称"扔掉"Commit.尝试收集时,您不知道Change属于哪个Commit。为了保留这些信息,我建议创建一个小型的帮助程序类(不过,您可以使用简单的 Pair(:

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()

最新更新