其实partitioning属于groupingBy的一种特殊情况,那就是二分,分成两组。
- Map
> partitionedMenu = menu.stream() - .collect(partitioningBy(Dish::isVegetarian));
-
- List
vegetarianDishes = partitionedMenu.get(true);
根据partitioningBy的条件,分为True和False各一组。
但是这种又可以直接使用filter来实现:
- List
vegetarianDishes = menu.stream() - .filter(Dish::isVegetarian).collect(toList());
我们来看看更高级一些的用法:
1. 二次分组,先partitioningBy再groupingBy
- Map
>> vegetarianDishesByType = menu.stream() - .collect(partitioningBy(Dish::isVegetarian,
- groupingBy(Dish::getType)));
相当于先进行了一次二分组,划分出是否素食,然后在素食和非素食内部再根据type进行分组。
2. 先二分,再求算最大值
- Map
mostCaloricPartitionedByVegetarian = menu.stream().collect( - partitioningBy(Dish::isVegetarian,
- collectingAndThen(maxBy(comparingInt(Dish::getCalories)),
- Optional::get)));
先进行了一次二分组,划分出是否素食,然后素食和非素食内部根据Calories进行比较,找到最大的Dish,然后取到。
在这里看,partitioningBy和groupingBy没有太大的区别,一个是多分组,另外一个是二分罢了。
一个实例,判断质数合数:
- public boolean isPrime(int candidate) {
- return IntStream.range(2, candidate).noneMatch(i -> candidate % i == 0);
- }
实际上不需要计算这么多,只需要到平方根即可:
- public boolean isPrime(int candidate) {
- int candidateRoot = (int) Math.sqrt((double) candidate);
- return IntStream.rangeClosed(2, candidateRoot)
- .noneMatch(i -> candidate % i == 0);
- }
根据我们上述方法,可以进行二分了:
- public Map
> partitionPrimes(int n) { - return IntStream.rangeClosed(2, n)
- .boxed()
- .collect(partitioningBy(candidate -> isPrime(candidate)));
- }
附录:所有收集器

