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