简体   繁体   English

填写地图 <String,Map<String,Integer> &gt;与流

[英]Fill Map<String,Map<String,Integer>> with Stream

I have a Linkedlist with Data ( author, date , LinkedList<Changes(lines, path)> ) 我有一个带有数据的( author, date , LinkedList<Changes(lines, path)> )

now i want to create with a stream out of this a Map< Filepath, Map< Author, changes >> 现在我想用这个流创建一个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)));
}

I try it so but this doesnt work. 我这样尝试,但这行不通。 How can i create this Map in a Map with the Stream and count at the same time the changes ? 如何在带有Stream的Map中创建此Map并同时计算更改?

Jeremy Grand is completely correct in his comment: in your collector it has long been forgotten that you started out from a stream of Commit objects, so you cannot use Commit::getAuthorName there. 杰里米·格兰德(Jeremy Grand)的评论完全正确:在收藏家中,人们早就忘记了您是从Commit对象流开始的,因此您不能在其中使用Commit::getAuthorName The challenge is how to keep the author name around to a place where you also got the path. 面临的挑战是如何将作者姓名保留在您也可以找到路径的地方。 One solution is to put both into a newly created string array (since both are strings). 一种解决方案是将两者都放入新创建的字符串数组中(因为两者都是字符串)。

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() insists on counting into a Long , not Integer , so I have modified your return type. Collectors.counting()坚持要计数为Long而不是Integer ,因此我修改了您的返回类型。 I'm sure a conversion to Integer would be possible if necessary, but I would first consider whether I could live with Long . 我敢肯定,如有必要,可以转换为Integer ,但是我首先考虑是否可以和Long住。

It's not the most beautiful stream code, and I will wait to see if other suggestions come up. 这不是最漂亮的流代码,我将等待看看是否有其他建议。

The code is compiled, but since I neither have your classes nor your data, I have not tried running it. 该代码已编译,但是由于我既没有您的类也没有您的数据,所以我没有尝试运行它。 If there are any issues, please revert. 如果有任何问题,请还原。

Your mistake is that map/flatMap call "throws away" the Commit . 您的错误是map/flatMap调用“丢弃”了Commit You do not know which Commit a Change belongs to when trying to collect. 尝试收集时,您不知道哪个Change属于哪个Commit Change In order to keep that information I'd recommend creating a small helper class (you could use a simple Pair, though): 为了保留这些信息,我建议创建一个小的帮助程序类(不过,您可以使用一个简单的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(); };
}

You can then flatMap to that, group it by path and author, and then sum up the lines changed: 然后,您可以将flatMap设置为该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))));

In case you do not want to sum up the lines, but just count the Changes , replace Collectors.summingInt(OneChange::getLines) by Collectors.counting() . 如果您不想汇总行数,而只是计算Changes ,请用Collectors.summingInt(OneChange::getLines)替换Collectors.summingInt(OneChange::getLines) Collectors.counting()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 流 <String> 到地图 <String, Integer> - Stream<String> to Map<String, Integer> 展平地图<Integer, List<String> &gt; 到地图<String, Integer>使用流和 lambda - Flatten a Map<Integer, List<String>> to Map<String, Integer> with stream and lambda 转换地图 <Integer, List<Object> &gt;到地图 <Integer, Map<String, Map<LocalDate, Integer> &gt;&gt;使用Java流API - Convert Map<Integer, List<Object>> to Map<Integer, Map<String, Map<LocalDate, Integer>>> using Java stream API Java 8流到Map <Integer, List<String> &gt; - Java 8 stream to Map<Integer, List<String>> 收集 Map<string, integer> 来自 Map 的 stream <string, map<string, integer> &gt;</string,></string,> - Collect Map<String, Integer> from stream of Map<String, Map<String, Integer>> 地图 <Integer, String> 还是String []? - Map<Integer, String> or String[]? Java 8 stream Map <string, map<string, integer> &gt; 如果根 map 密钥包含,则返回 map 值</string,> - Java 8 stream Map<String, Map<String, Integer>> return map values if root map key contains 如何转换流 <Map<Integer, String> &gt;来映射java 8 - How to convert Stream<Map<Integer, String>> to map java 8 Java 流收集到 Map <String, Map<Integer, MyObject> &gt; - Java stream collect to Map<String, Map<Integer, MyObject>> 地图 <String, Integer> 和地图 <Integer ,String> 排序 - Map<String, Integer> and Map<Integer ,String> sorting
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM