2015-06-22 6 views
5

Aus Gründen der diesem Beispiel nehmen wir an, ich habe eine einfache Art Tuple mit zwei Attributen:Map Werte in Collectors.groupingBy()

interface Tuple<T, U> { 
    T getFirst(); 
    U getSecond(); 
} 

Jetzt möchte ich eine Sammlung von (first, second) Tupeln in einer Karte zu transformieren welches jeden first Wert auf eine Menge aller second Werte abbildet, die in Tupeln mit dem spezifischen first Wert enthalten sind. Das Verfahren groupSecondByFirst() zeigt eine mögliche Implementierung zu tun, was ich will:

<T, U> Map<T, Set<U>> groupSecondByFirst(Set<Tuple<T, U>> tuples) { 
    Map<T, Set<U>> result = new HashMap<>(); 

    for (Tuple<T, U> i : tuples) { 
     result.computeIfAbsent(i.getFirst(), x -> new HashSet<>()).add(i.getSecond()); 
    } 

    return result; 
} 

Wenn der Eingang war [(1, "one"), (1, "eins"), (1, "uno"), (2, "two"), (3, "three")] der Ausgang { 1 = ["one", "eins", "uno"], 2 = ["two"], 3 = ["trhee"] }

würde Ich mag wäre wissen, ob und wie ich diese die Ströme Framework implementieren kann. Das Beste, was ich habe ist der folgende Ausdruck, der eine Karte zurückgibt, die die volle Tupel als Werte enthält und nicht nur ihre second Elemente:

Map<T, Set<Tuple<T, U>>> collect = tuples.stream().collect(
    Collectors.groupingBy(Tuple::getFirst, Collectors.toSet())); 

Antwort

13

ich eine Lösung gefunden; Dabei handelt es sich um Collections.mapping(), die einen Kollektor umhüllen kann und eine Abbildungsfunktion anwendet, die auf alle Elemente angewendet wird, bevor sie dem umwickelten Kollektor zugeführt werden:

static <T, U> Map<T, Set<U>> groupSecondByFirst(Collection<Tuple<T, U>> tuples) { 
    return tuples 
     .stream() 
     .collect(
      Collectors.groupingBy(
       Tuple::getFirst, 
       Collectors.mapping(
        Tuple::getSecond, 
        Collectors.toSet()))); 
} 
Verwandte Themen