Der Titel ist großartig, aber Collectors.groupingBy ist einfach eine großartige Geschichte.
In letzter Zeit gab es viele Fälle, in denen verschiedene Karten mit groupingBy erstellt wurden (aus irgendeinem Grund gab es nur wenige Fälle, in denen Karten erstellt wurden, sodass ich sie nicht häufig verwendete). Dieser Artikel ist eine Zusammenfassung dessen, was zu dieser Zeit untersucht wurde.
Java10 Lombok
Das Gute an Collectors.groupingBy ist, dass Sie sie einfach aggregieren können, indem Sie ihnen einen Schlüssel geben. Wenn Sie den Wert von Map ändern möchten, können Sie ein weiteres Argument hinzufügen und dort schreiben, sodass die Aggregation in verschiedenen Fällen unterstützt wird.
List<Integer> nums = List.of(1,2,3,4,5,6,7,8,9,1,1,1);
Map<Integer,List<Integer>> map = nums.stream().collect(Collectors.groupingBy(i ->i));
System.out.println(map);
=> {1=[1, 1, 1, 1], 2=[2], 3=[3], 4=[4], 5=[5], 6=[6], 7=[7], 8=[8], 9=[9]}
Das größte Merkmal von groupingBy ist jedoch, dass es auch dann gut funktioniert, wenn Sie komplizierte Schlüssel festlegen. Das Festlegen mehrerer Schlüssel ist sehr einfach. Übergeben Sie bei der Angabe der Schlüssel einfach mehrere Felder. "-" Wird hinzugefügt, um das Anzeigen zu vereinfachen, aber ohne ist es in Ordnung.
Als Schlüssel werden diesmal Name1 und Name2 als Schlüssel festgelegt.
public static void main(String[] arg) {
List<String> names = List.of("taro", "jiro", "saburo");
List<Name> nameList = names.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
Map<String,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + "-" + it.getName2()));
System.out.println(map);
// => {jiro-jiro=[Main.Name(name1=jiro, name2=jiro, name3=jiro)], saburo-saburo=[Main.Name(name1=saburo, name2=saburo, name3=saburo)], taro-taro=[Main.Name(name1=taro, name2=taro, name3=taro)]}
}
@Data
private static class Name {
private String name1;
private String name2;
private String name3;
public Name(String name1, String name2, String name3) {
this.name1 = name1;
this.name2 = name2;
this.name3 = name3;
}
}
Allein damit hat name3 den gleichen Wert, sodass Sie nicht erkennen können, ob name1 und name2 die Schlüssel sind. Daher möchte ich der Liste einen neuen Namen ("Taro", "Jiro", "Taro") hinzufügen und sehen, welche Art von Karte erstellt werden kann.
public static void main(String[] arg) {
List<String> names = List.of("taro", "jiro", "saburo");
List<Name> nameList = names.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
nameList.add(new Name("taro", "jiro", "taro"));
Map<String,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + "-" + it.getName2()));
System.out.println(map);
// => {jiro-jiro=[Main.Name(name1=jiro, name2=jiro, name3=jiro)], saburo-saburo=[Main.Name(name1=saburo, name2=saburo, name3=saburo)], taro-taro=[Main.Name(name1=taro, name2=taro, name3=taro)], taro-jiro=[Main.Name(name1=taro, name2=jiro, name3=taro)]}
}
Wie Sie dem Ergebnis entnehmen können, ist das diesmal hinzugefügte Objekt unabhängig als "taro-jiro = [Hauptname (Name1 = Taro, Name2 = Jiro, Name3 = Taro)]", also sind Name1 und Name2 Sie können sehen, dass es der Schlüssel war.
Was hier besorgniserregend ist, ist, dass der resultierende Name3 "Taro" enthält. Das Tolle an groupingBy ist, dass es dasselbe wie jedes andere Feld für andere Werte als die im Schlüssel angegebenen tut.
Ich möchte mit name1 und name3 als Schlüssel ausführen, um zu überprüfen, ob es wahr ist.
public static void main(String[] arg) {
List<String> names = List.of("taro", "jiro", "saburo");
List<Name> nameList = names.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
nameList.add(new Name("taro", "jiro", "taro"));
Map<String,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + "-" + it.getName3()));
System.out.println(map);
// => {jiro-jiro=[Main.Name(name1=jiro, name2=jiro, name3=jiro)], saburo-saburo=[Main.Name(name1=saburo, name2=saburo, name3=saburo)], taro-taro=[Main.Name(name1=taro, name2=taro, name3=taro), Main.Name(name1=taro, name2=jiro, name3=taro)]}
}
Wenn Sie das Ausführungsergebnis überprüfen, ist das als "neuer Name" ("Taro", "Jiro", "Taro") hinzugefügte Objekt "Taro-Taro = [Hauptname (Name1 = Taro, Name2 = Taro, Name3 = Taro)". ), Main.Name (name1 = taro, name2 = jiro, name3 = taro)] und wird wie erwartet als Wert des Schlüssels von
taro-taro` registriert.
Schauen wir uns ein anderes Muster von Beispielen für Name1 und Name3 an. Sie können die Felder bis zum vorherigen Beispiel sehen, aber schauen wir uns auch das Beispiel an, in dem Name1 und Name3 vertauscht werden.
public static void main(String[] arg) {
List<String> names = List.of("taro", "jiro", "saburo");
List<Name> nameList = names.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
nameList.add(new Name("taro", "jiro", "taro"));
nameList.add(new Name("jiro", "taro", "taro"));
Map<String,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + "-" + it.getName3()));
System.out.println(map);
// => {jiro-jiro=[Main.Name(name1=jiro, name2=jiro, name3=jiro)], saburo-saburo=[Main.Name(name1=saburo, name2=saburo, name3=saburo)], jiro-taro=[Main.Name(name1=jiro, name2=taro, name3=taro)], taro-taro=[Main.Name(name1=taro, name2=taro, name3=taro), Main.Name(name1=taro, name2=jiro, name3=taro)]}
}
Es scheint, dass selbst wenn Sie die Reihenfolge ändern, es richtig reagiert.
Ich habe das vorherige Beispiel mit Integer-Typ versucht.
public static void main(String[] arg) {
List<Integer> nums = List.of(1,2,3);
List<Name> nameList = nums.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
nameList.add(new Name(1, 2, 1));
nameList.add(new Name(2, 1, 1));
Map<Integer,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + it.getName2()));
System.out.println(map);
}
@Data
private static class Name {
private Integer name1;
private Integer name2;
private Integer name3;
public Name(Integer name1, Integer name2, Integer name3) {
this.name1 = name1;
this.name2 = name2;
this.name3 = name3;
}
}
In diesem Fall scheint es durch das Berechnungsergebnis des Schlüssels aggregiert zu werden. Es wäre seltsam, wenn es mehrere Schlüssel mit demselben Schlüssel gäbe, also bin ich überzeugt.
Es scheint, dass es durch das Berechnungsergebnis aggregiert wird, aber überprüfen Sie für alle Fälle, ob Sie es im Feld sehen können.
public static void main(String[] arg) {
List<Integer> nums = List.of(1,2,3);
List<Name> nameList = nums.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
nameList.add(new Name(1, 1, 2));
nameList.add(new Name(1, 2, 1));
Map<Integer,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + it.getName3()));
System.out.println(map);
// => 2=[Main.Name(name1=1, name2=1, name3=1), Main.Name(name1=1, name2=2, name3=1)], 3=[Main.Name(name1=1, name2=1, name3=2)], 4=[Main.Name(name1=2, name2=2, name3=2)], 6=[Main.Name(name1=3, name2=3, name3=3)]}
}
@Data
private static class Name {
private Integer name1;
private Integer name2;
private Integer name3;
public Name(Integer name1, Integer name2, Integer name3) {
this.name1 = name1;
this.name2 = name2;
this.name3 = name3;
}
}
Er sah es auch in Integer-Typ.
Dies ist der dritte Versuch vom Typ Integer. Angenommen, Sie konvertieren den Schlüssel in eine Zeichenfolge und verwenden ihn als Schlüssel.
public static void main(String[] arg) {
List<Integer> nums = List.of(1,2,3);
List<Name> nameList = nums.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
nameList.add(new Name(1, 2, 1));
nameList.add(new Name(2, 1, 1));
Map<String,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + "-" + it.getName2()));
System.out.println(map);
// => {1-1=[Main.Name(name1=1, name2=1, name3=1)], 2-1=[Main.Name(name1=2, name2=1, name3=1)], 1-2=[Main.Name(name1=1, name2=2, name3=1)], 2-2=[Main.Name(name1=2, name2=2, name3=2)], 3-3=[Main.Name(name1=3, name2=3, name3=3)]}
}
@Data
private static class Name {
private Integer name1;
private Integer name2;
private Integer name3;
public Name(Integer name1, Integer name2, Integer name3) {
this.name1 = name1;
this.name2 = name2;
this.name3 = name3;
}
}
In diesem Fall scheint die Reihenfolge berücksichtigt zu werden.
Lassen Sie uns prüfen, ob es kein Problem gibt, auch wenn wir die Anzahl der Schlüssel erhöhen.
public static void main(String[] arg) {
List<String> names = List.of("taro", "jiro", "saburo");
List<Name> nameList = names.stream().map(it -> new Name(it, it, it)).collect(Collectors.toList());
nameList.add(new Name("taro","taro","jiro"));
nameList.add(new Name("taro","jiro","taro"));
Map<String,List<Name>> map = nameList.stream()
.collect(Collectors.groupingBy(it -> it.getName1() + "-" + it.getName2() + "-" + it.getName3()));
System.out.println(map);
// => {jiro-jiro-jiro=[Main.Name(name1=jiro, name2=jiro, name3=jiro)], taro-jiro-taro=[Main.Name(name1=taro, name2=jiro, name3=taro)], taro-taro-taro=[Main.Name(name1=taro, name2=taro, name3=taro)], taro-taro-jiro=[Main.Name(name1=taro, name2=taro, name3=jiro)], saburo-saburo-saburo=[Main.Name(name1=saburo, name2=saburo, name3=saburo)]}
}
@Data
private static class Name {
private String name1;
private String name2;
private String name3;
public Name(String name1, String name2, String name3) {
this.name1 = name1;
this.name2 = name2;
this.name3 = name3;
}
}
Es scheint in Ordnung zu sein, die Anzahl der Schlüssel zu erhöhen.
Ich dachte, ich würde ein bisschen mehr versuchen, aber jetzt, da ich die Tendenz begriffen habe, fasse ich abschließend die Operation des Aufstiegs zusammen.
Grundsätzlich scheint es sich um eine Methode zu handeln, die das im Schlüssel angegebene Feld gemäß dem Lambda-Ausdruck erstellt und nach diesem Wert aggregiert. Wenn es sich um einen Zeichenfolgentyp handelt, können Sie sehen, dass die angegebene Reihenfolge und das Feld verknüpft sind und der Schlüssel ist. Wenn es sich um einen numerischen Typ handelt, können Sie feststellen, ob das erstellte Ergebnis dasselbe ist, da das Berechnungsergebnis des angegebenen Felds der Schlüssel ist. Ich werde.
Es stellt sich heraus, dass goupingBy wirklich mächtig ist. In Kombination mit anderen Methoden in Collectors kann es sogar noch stärker sein, aber ich möchte eine andere Gelegenheit nutzen (ich weiß nicht, ob es eine gibt).
Übrigens habe ich mich in diesem Artikel nicht mit der internen Verarbeitung von Java befasst, daher weiß ich nicht, warum dies passiert!
Recommended Posts