2015-10-26 6 views
9

Ich habe die folgende Klasse.Java 8 Gruppierung mit benutzerdefinierten Kollektor?

Ich möchte in der Lage sein, nach Alter zu gruppieren und dann die Liste der Personennamen anstatt das Objekt Person selbst zu sammeln; Alles in einem einzigen schönen Lamba-Ausdruck.

Um all dies zu vereinfachen, verbinde ich meine aktuelle Lösung, die das Ergebnis der Gruppierung nach Alter speichert und dann iteriert, um die Namen zu sammeln.

ArrayList<OtherPerson> members = new ArrayList<>(); 

members.add(new OtherPerson("Fred", IsoChronology.INSTANCE.date(1980, 6, 20), OtherPerson.Sex.MALE, "[email protected]")); 
members.add(new OtherPerson("Jane", IsoChronology.INSTANCE.date(1990, 7, 15), OtherPerson.Sex.FEMALE, "[email protected]")); 
members.add(new OtherPerson("Mark", IsoChronology.INSTANCE.date(1990, 7, 15), OtherPerson.Sex.MALE, "[email protected]")); 
members.add(new OtherPerson("George", IsoChronology.INSTANCE.date(1991, 8, 13), OtherPerson.Sex.MALE, "[email protected]")); 
members.add(new OtherPerson("Bob", IsoChronology.INSTANCE.date(2000, 9, 12), OtherPerson.Sex.MALE, "[email protected]")); 

Map<Integer, List<Person>> collect = members.stream().collect(groupingBy(Person::getAge)); 

Map<Integer, List<String>> result = new HashMap<>(); 

collect.keySet().forEach(key -> { 
      result.put(key, collect.get(key).stream().map(Person::getName).collect(toList())); 
}); 

Current solution

nicht ideal und zum Wohl des Lernens ich eine elegantere und leistungsfähigste Lösung haben möchte.

Antwort

9

Wenn ein Strom mit Collectors.groupingBy Gruppierung Sie eine Reduktionsoperation auf die Werte mit einem benutzerdefinierten angeben Collector . Hier müssen wir Collectors.mapping verwenden, die eine Funktion (was das Mapping ist) und einen Kollektor (wie man die abgebildeten Werte sammelt) verwendet. In diesem Fall lautet die Zuordnung Person::getName, d. H. Eine Methodenreferenz, die den Namen der Person zurückgibt, und wir sammeln diese in eine List.

Map<Integer, List<String>> collect = 
    members.stream() 
      .collect(Collectors.groupingBy(
       Person::getAge, 
       Collectors.mapping(Person::getName, Collectors.toList())) 
      ); 
+0

Ops, das war einfach eh! Prost! – lcardito

0

können Sie verwenden eine mappingCollector die Liste der Person auf eine Liste von Personennamen zuzuordnen:

Map<Integer, List<String>> collect = 
    members.stream() 
      .collect(Collectors.groupingBy(Person::getAge, 
              Collectors.mapping(Person::getName, Collectors.toList()))); 
1

Sie können auch Collectors.toMap wird und die eine Zuordnung für Schlüssel, Wert und Merge-Funktion (falls vorhanden).

Map<Integer, String> ageNameMap = 
    members.stream() 
      .collect(Collectors.toMap(
       person -> person.getAge(), 
       person -> person.getName(), (pName1, pName2) -> pName1+"|"+pName2) 
    );