2016-12-05 83 views
0

我正在使用收集器的groupingBy和partioningBy函数。与人的名单我的工作,人员名单如下:在使用PartioningBy和groupingBy时无法获得所需的输出

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)); 

我要的是分区的名字的人的基础上,列表以字母“P”,然后他们在组启动他们的年龄的基础。 这里是我的代码,它可以完成上述过滤:

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

而我得到的输出是:

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

现在,我的要求是,从上面的结果只得到内部地图。也就是说,我想改变返回值:

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

就是我想要的结果(或分区地图),其布尔值由partioningBy函数返回是真实的。我怎样才能做到这一点?

+1

*为什么*你想要这个?在*'.collect(Collectors.groupingBy(p - > p.age> 20))'前面做一个'filter(p - > p.name.startsWith(“P”))'''。否则,如果您希望收集之后未使用的数据,请按照问题中的提示进行操作,并对结果调用“get(true)”。 – Holger

+0

不明确的原因。只要看看这个特定场景是否有任何方法。 – KayV

+1

那么,你可以过滤之前或之后提取。两者都很简单。你还有什么想法? – Holger

回答

1

应用分区,您可以创建一个自定义收集器(我已经做到了只作为练习,请把它看作) :

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); 
    } 
} 

然后应用它像这样:

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. 过滤器由name
  2. 通过age

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