2017-06-20 3 views
2

Ich habe eine LinkedList mit Daten (author, date , LinkedList<Changes(lines, path)>)Fill Map <String, Map <String, Integer >> mit Stream-

jetzt i mit einem Strom erzeugen wollen diese aus einem 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))); 
} 

Ich versuche, Es ist so, aber das funktioniert nicht. Wie kann ich diese Map in einer Map mit dem Stream erstellen und gleichzeitig die Änderungen zählen?

+1

In Ihrer zweiten 'toMap' sind Ihre Elemente' Changes' und nicht 'Commit' mehr. –

+1

Mögliches Duplikat von [Java8: HashMap zu HashMap mit Stream/Map-Reduce/Collector] (https://stackoverflow.com/questions/25903137/java8-hashmapx-y-to-hashmapx-z-using-stream- map-reducte-collector) –

Antwort

3

Jeremy Grand ist völlig korrekt in seinem Kommentar: In Ihrem Sammler ist es längst vergessen, dass Sie aus einem Strom von Commit Objekte gestartet, so dass Sie Commit::getAuthorName dort nicht verwenden können. Die Herausforderung besteht darin, den Namen des Autors an einem Ort zu halten, an dem Sie auch den Pfad haben. Eine Lösung besteht darin, beide in ein neu erstelltes String-Array zu schreiben (da beide Strings sind).

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() besteht darauf, in ein Long auf zu zählen, nicht Integer, so habe ich Ihren Rückgabetyp geändert. Ich bin mir sicher, dass eine Konvertierung nach Integer möglich wäre, aber ich würde zuerst überlegen, ob ich mitleben könnte.

Es ist nicht die schönste Stream-Code, und ich werde warten, um zu sehen, ob andere Vorschläge kommen.

Der Code ist kompiliert, aber da ich weder Ihre Klassen noch Ihre Daten habe, habe ich nicht versucht, es auszuführen. Wenn es irgendwelche Probleme gibt, bitte zurück.

+1

Ich habe es getestet und es funktioniert super, danke! – Drextor

0

Ihr Fehler ist, dass map/flatMap Anruf "wirft" die Commit. Sie wissen nicht, welche Commit a Change gehört, wenn Sie versuchen zu sammeln. Um diese Informationen zu erhalten würde ich empfehlen, eine kleine Hilfsklasse zu schaffen (man könnte ein einfaches Paar, obwohl verwenden):

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

Sie können dann flatMap zu, dass Gruppe durch Pfad und Autor, und dann Summe bis die Linien geändert:

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

Falls Sie nicht wollen, die Zeilen summieren, aber zählen nur die Changes, ersetzen Collectors.summingInt(OneChange::getLines) durch Collectors.counting().

Verwandte Themen