2016-12-05 1 views
0

Ich arbeite mit Sammlern SammyBy und partitioningBy Funktionen. Ich eine Arbeit mit einer Liste von Personen, die Liste der Personen wie folgt:Nicht in der Lage, die gewünschte Ausgabe zu erhalten, während ich mit PartioningBy und groupingBy zusammenarbeite

List<Person> persons = 
     Arrays.asList(
      new Person("Max", 18), 
      new Person("Peter", 23), 
      new Person("Pamela", 23), 
      new Person("David", 12), 
      new Person("Pam", 12)); 

Was ich will, ist die Liste auf der Grundlage von Personen, dessen Namen beginnt mit dem Buchstaben „P“ und auf dann die Gruppe partitionieren die Grundlage ihres Alters. Hier ist mein Code, die die obige Filtration tut:

Map<Boolean, Map<Object, List<Person>>> rr = persons.stream() 
              .collect(Collectors.partitioningBy(p -> p.name.startsWith("P"), 
                Collectors.groupingBy(p -> p.age > 20))); 

Und die Ausgabe, die ich habe ist:

rr = {false={false=[Max, David]}, true={false=[Pam], true=[Peter, Pamela]}} 

Nun, meine Forderung ist nur interne Karte aus den obigen Ergebnissen zu erhalten. Das heißt, ich will die Rückgabewerte ändern:

{false=[Pam], true=[Peter, Pamela]} 

Das heißt, ich die Ergebnisse (oder partitionierten Karte) wollen deren boolean Wert gilt als durch die partioningBy Funktion zurückgegeben. Wie kann ich das erreichen?

+1

* Warum * willst du das? Mach einfach einen 'filter (p -> p.name.startsWith (" P "))' * vor * '.collect (Collectors.groupingBy (p -> p.age> 20))' '. Andernfalls, wenn Sie Daten sammeln möchten, die Sie danach nicht verwenden, tun Sie einfach wie in Ihrer Frage gepostet und rufen Sie 'get (true)' auf dem Ergebnis auf. – Holger

+0

Nicht spezifisch für den Grund. Ich sehe nur nach, ob es ein bestimmtes Szenario gibt. – KayV

+1

Nun, Sie können vorher filtern oder extrahieren. Beides ist einfach. Was hast du noch vor? – Holger

Antwort

1

Sie eine benutzerdefinierte Collector erstellen könnte (ich habe es nur als eine Übung gemacht, fügen Sie es als solches behandeln) :

static class MyCustom<T, U> implements Collector<Person, List<Person>, Map<T, List<U>>> { 

    private final Function<Person, T> function; 

    private final Predicate<Person> predicate; 

    private final Function<Person, U> transformingFunction; 

    public MyCustom(Predicate<Person> predicate, Function<Person, T> function, 
      Function<Person, U> transformingFunction) { 
     this.predicate = predicate; 
     this.function = function; 
     this.transformingFunction = transformingFunction; 
    } 

    @Override 
    public Supplier<List<Person>> supplier() { 
     return ArrayList::new; 
    } 

    @Override 
    public BiConsumer<List<Person>, Person> accumulator() { 
     return (list, person) -> { 
      if (predicate.test(person)) { 
       list.add(person); 
      } 
     }; 
    } 

    @Override 
    public BinaryOperator<List<Person>> combiner() { 
     return (l1, l2) -> { 
      l1.addAll(l2); 
      return l1; 
     }; 
    } 

    @Override 
    public Function<List<Person>, Map<T, List<U>>> finisher() { 
     return list -> { 
      return list.stream().collect(
        Collectors.groupingBy(function, Collectors.mapping(transformingFunction, Collectors.toList()))); 
     }; 
    } 

    @Override 
    public Set<java.util.stream.Collector.Characteristics> characteristics() { 
     return EnumSet.of(Characteristics.UNORDERED); 
    } 
} 

Und dann wenden Sie es an wie folgt:

MyCustom<Integer, String> custom = new MyCustom<>((Person p) -> p.getName().startsWith("P"), 
      (Person p) -> p.getAge(), Person::getName); 

System.out.println(persons.stream().collect(custom)); // {23=[Peter, Pamela], 12=[Pam]} 
1
  1. Filter nach name
  2. Partitionierung Nehmen von age

    Map<Boolean, List<Person>> p1 = persons.stream().filter(p -> p.name.startsWith("P")).collect(Collectors.partitioningBy(p -> p.getAge() > 20)); 
    
Verwandte Themen