2017-06-29 5 views
2

Zum Beispiel habe ich eine Liste von Studenten mit ihren Semestern und Themen.Gruppe nach mehreren Werten

Subject Semester Attendee 
--------------------------------- 
ITB001 1   John 
ITB001 1   Bob 
ITB001 1   Mickey 
ITB001 2   Jenny 
ITB001 2   James 
MKB114 1   John 
MKB114 1   Erica 

Wenn ich zu einer Gruppe müssen sie um einen Wert mit Stream api, kann ich so etwas machen;

Map<String, List<Student>> studlistGrouped = 
    studlist.stream().collect(Collectors.groupingBy(w -> w.getSubject())); 

und es funktioniert. Wenn ich sie jedoch mit zwei oder mehr Werten (wie den Sql-Handles) gruppieren möchte, kann ich nicht herausfinden, wie ich vorgehen muss.

Antwort

1

Ein Ansatz besteht darin, nach einer Klasse zu gruppieren, die alle Felder enthält, die Sie gruppieren möchten. Diese Klasse muss diese Felder hashCode und equals mit alle implementieren, um wie erwartet zu funktionieren.

In Ihrem Beispiel hierfür wäre:

public class SubjectAndSemester { 

    private final String subject; 

    private final int semester; // an enum sounds better 

    public SubjectAndSemester(String subject, int semester) { 
     this.subject = subject; 
     this.semester = semester; 
    } 

    // TODO getters and setters, hashCode and equals using both fields 
} 

Dann sollten Sie diese Methode in Ihrer Student Klasse erstellen:

public SubjectAndSemester bySubjectAndSemester() { 
    return new SubjectAndSemester(subject, semester); 
} 

Jetzt können Sie sich wie folgt dar:

Map<SubjectAndSemester, List<Student>> studlistGrouped = studlist.stream() 
    .collect(Collectors.groupingBy(Student::bySubjectAndSemester)); 

Dies erstellt eine einstufige Gruppierung von Schülern.


Es gibt eine andere Option, die Sie ein Tuple verwenden erfordert keine oder eine neue Klasse Gruppe zu erstellen. Ich meine, Sie eine n -Niveau Gruppierung von Studenten haben können, durch nachgeschaltete groupingBy Kollektoren:

Map<String, Map<Integer, List<Student>>> studlistGrouped = studlist.stream() 
    .collect(Collectors.groupingBy(Student::getSubject, 
     Collectors.groupingBy(Student::getSemester))); 

Dies schafft eine 2-Level-Gruppierung, so dass die zurück Struktur ist nun eine Karte von Karten von Listen. Wenn Sie damit leben können, selbst wenn Sie mehrere Ebenen gruppieren, können Sie vermeiden, eine Klasse zu erstellen, die als Schlüssel der Karte fungiert.

+0

Vielen Dank für Ihre Antwort. Deine Antwort sieht gut aus, aber mein Problem ist, dass ich mein Beispiel hier vereinfacht habe. Basierend auf der Benutzerauswahl sollte ich nicht nach Gruppen gruppieren oder mit bis zu 8 Variablen gruppieren. In Ihrer ersten Lösung sollte ich Tausende von verschiedenen Kombinationen für jede Möglichkeit erstellen. – drJava

+0

@drJava Nicht unbedingt ... Sie könnten in Ihrem feinkörnigsten Szenario eine Klasse mit diesen 8 Feldern erstellen, nach denen Sie gruppieren möchten. Wenn der Benutzer dann nicht 8 Felder zum Gruppieren ausgewählt hat, setzen Sie einfach die nicht ausgewählten Felder auf "null" und machen "hashCode" und "equals" so, als wären diese Nullfelder nicht vorhanden, dh "hashCode" für ein Nullfeld sollte 0 sein. Und für "equals" einfach mit "null" vergleichen. Eclipse und IntelliJ machen das automatisch für Sie. –

+0

Das heißt, ich brauche nur eine Methode, wie bySubjectAndSemester in Ihrem Beispiel und die Felder zu erzeugen, die durch nicht gruppiert werden soll, null gesetzt werden und der Rest ist, wie Sie in Ihrem Kommentar geschrieben haben? – drJava

0

Sie könnten ein berechnetes Feld erstellen, die Kombination der beiden Säulen ist

Map<String, List<Student>> studlistGrouped = 
    studlist.stream().collect(Collectors.groupingBy(w -> w.getSubject() + "-" w.getAttendee())); 

EDIT:
Eine andere „geeignete“ Lösung: zu this blog post accoridng, benötigen Sie eine Tuple Klasse zu definieren, die können Halten Sie die zwei Spalten:

+0

Ich werde es jetzt versuchen und eine Rückmeldung dafür geben. Danke für deine Antwort. – drJava

+0

Hier im Beispiel habe ich mein Beispiel vereinfacht. Die tatsächliche Implementierung wird so sein; basierend auf dem Benutzereintrag kann es nicht durch oder bis zu 8 Felder gruppiert werden, es kann gruppiert werden. Ich denke auch, dass dieses Beispiel mit dem Tupel für meinen Fall passender sein könnte. – drJava

+1

... es ist erstaunlich, wie Google-Suchmaschine ist nützlich ... –

Verwandte Themen