【问题标题】:Fill Map<String,Map<String,Integer>> with Stream用 Stream 填充 Map<String,Map<String,Integer>>
【发布时间】:2017-11-22 21:34:21
【问题描述】:

我有一个带有数据的链表( author, date , LinkedList&lt;Changes(lines, path)&gt; )

现在我想用 Map&lt; Filepath, Map&lt; Author, changes &gt;&gt; 的流创建一个流

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 的地图中创建此地图并同时计算更改?

【问题讨论】:

标签: java java-8 java-stream


【解决方案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 一起生活。

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

代码已编译,但由于我既没有你的类也没有你的数据,所以我没有尝试运行它。如果有任何问题,请回复。

【讨论】:

    【解决方案2】:

    您的错误是map/flatMap 调用“丢弃”Commit。尝试收集时,您不知道CommitChange 属于哪个。为了保留这些信息,我建议创建一个小型辅助类(不过,您可以使用简单的 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()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-08
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      相关资源
      最近更新 更多