本文目录导读:

Java 中 Collectors.partitioningBy 案例详解
partitioningBy 是 Java Stream API 中的一个收集器,用于根据 Predicate 条件将元素分为两组(true 和 false),它返回一个 Map<Boolean, List<T>>。
基础用法
案例1:按数字奇偶性分区
import java.util.*;
import java.util.stream.Collectors;
public class BasicPartitioning {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 按奇偶数分区
Map<Boolean, List<Integer>> partitioned = numbers.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
System.out.println("偶数: " + partitioned.get(true));
System.out.println("奇数: " + partitioned.get(false));
// 输出:
// 偶数: [2, 4, 6, 8, 10]
// 奇数: [1, 3, 5, 7, 9]
}
}
案例2:按字符串长度分区
public class StringPartitioning {
public static void main(String[] args) {
List<String> words = Arrays.asList("Java", "Python", "C", "JS", "Kotlin", "Rust");
// 按长度是否大于3分区
Map<Boolean, List<String>> partitioned = words.stream()
.collect(Collectors.partitioningBy(word -> word.length() > 3));
System.out.println("长度>3的单词: " + partitioned.get(true));
System.out.println("长度<=3的单词: " + partitioned.get(false));
// 输出:
// 长度>3的单词: [Java, Python, Kotlin, Rust]
// 长度<=3的单词: [C, JS]
}
}
使用下游收集器
案例3:分区后进行二次处理
import java.util.*;
import java.util.stream.Collectors;
public class DownstreamCollector {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 分区后统计每组的个数
Map<Boolean, Long> countByParity = numbers.stream()
.collect(Collectors.partitioningBy(
n -> n % 2 == 0,
Collectors.counting()
));
System.out.println("偶数个数: " + countByParity.get(true));
System.out.println("奇数个数: " + countByParity.get(false));
// 分区后求和
Map<Boolean, Integer> sumByParity = numbers.stream()
.collect(Collectors.partitioningBy(
n -> n % 2 == 0,
Collectors.summingInt(Integer::intValue)
));
System.out.println("偶数和: " + sumByParity.get(true));
System.out.println("奇数和: " + sumByParity.get(false));
}
}
案例4:复杂对象的分区处理
import java.util.*;
import java.util.stream.Collectors;
class Person {
private String name;
private int age;
private double salary;
public Person(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() { return name; }
public int getAge() { return age; }
public double getSalary() { return salary; }
@Override
public String toString() {
return name + "(" + age + "岁, " + salary + "元)";
}
}
public class ObjectPartitioning {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("张三", 25, 8000),
new Person("李四", 35, 15000),
new Person("王五", 30, 12000),
new Person("赵六", 28, 6000),
new Person("孙七", 45, 20000)
);
// 按是否超过30岁分区
Map<Boolean, List<Person>> byAge = people.stream()
.collect(Collectors.partitioningBy(p -> p.getAge() > 30));
System.out.println("30岁以上: " + byAge.get(true));
System.out.println("30岁及以下: " + byAge.get(false));
// 分区并按工资排序
Map<Boolean, List<Person>> bySalarySorted = people.stream()
.collect(Collectors.partitioningBy(
p -> p.getSalary() > 10000,
Collectors.collectingAndThen(
Collectors.toList(),
list -> list.stream()
.sorted(Comparator.comparingDouble(Person::getSalary))
.collect(Collectors.toList())
)
));
System.out.println("\n高薪员工(按工资排序): " + bySalarySorted.get(true));
System.out.println("低薪员工(按工资排序): " + bySalarySorted.get(false));
}
}
组合使用多个条件
案例5:多个条件组合分区
public class ComplexCondition {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
// 同时满足:能被2整除且大于5
Map<Boolean, List<Integer>> complex = numbers.stream()
.collect(Collectors.partitioningBy(
n -> n % 2 == 0 && n > 5
));
System.out.println("满足条件(偶数且>5): " + complex.get(true));
System.out.println("不满足条件: " + complex.get(false));
}
}
与其他收集器组合
案例6:分区后使用 joining
public class JoiningPartitioning {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
// 分区后连接成字符串
Map<Boolean, String> joined = words.stream()
.collect(Collectors.partitioningBy(
s -> s.length() > 5,
Collectors.joining(", ", "[", "]")
));
System.out.println("长单词: " + joined.get(true));
System.out.println("短单词: " + joined.get(false));
// 分区后转成 Set
Map<Boolean, Set<String>> sets = words.stream()
.collect(Collectors.partitioningBy(
s -> s.contains("a"),
Collectors.toSet()
));
System.out.println("含'a'的单词: " + sets.get(true));
System.out.println("不含'a'的单词: " + sets.get(false));
}
}
实际应用场景
案例7:数据分析
public class DataAnalysis {
public static void main(String[] args) {
List<Double> scores = Arrays.asList(85.5, 92.0, 78.5, 95.5, 60.0, 45.5, 88.0, 70.5, 55.0, 90.5);
// 及格/不及格分组
Map<Boolean, List<Double>> byPass = scores.stream()
.collect(Collectors.partitioningBy(score -> score >= 60));
// 统计各组成绩的平均值
Map<Boolean, Double> averages = scores.stream()
.collect(Collectors.partitioningBy(
score -> score >= 60,
Collectors.averagingDouble(Double::doubleValue)
));
System.out.println("及格人数: " + byPass.get(true).size());
System.out.println("不及格人数: " + byPass.get(false).size());
System.out.println("及格平均分: " + averages.get(true));
System.out.println("不及格平均分: " + averages.get(false));
}
}
性能优化与实际注意事项
案例8:处理大量数据
public class PerformanceExample {
public static void main(String[] args) {
// 生成100万个随机数
Random random = new Random();
List<Integer> data = random.ints(1_000_000, 1, 1000000)
.boxed()
.collect(Collectors.toList());
// 方式1:partitioningBy(推荐)
long start1 = System.currentTimeMillis();
Map<Boolean, Long> count1 = data.stream()
.collect(Collectors.partitioningBy(
n -> n > 500000,
Collectors.counting()
));
long end1 = System.currentTimeMillis();
System.out.println("partitioningBy耗时: " + (end1 - start1) + "ms");
// 方式2:groupingBy(等价的替代方案)
long start2 = System.currentTimeMillis();
Map<String, Long> count2 = data.stream()
.collect(Collectors.groupingBy(
n -> n > 500000 ? "big" : "small",
Collectors.counting()
));
long end2 = System.currentTimeMillis();
System.out.println("groupingBy耗时: " + (end2 - start2) + "ms");
}
}
嵌套分区
案例9:多级分区
public class NestedPartitioning {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
// 先按奇偶分,再按是否大于6分
Map<Boolean, Map<Boolean, List<Integer>>> nested = numbers.stream()
.collect(Collectors.partitioningBy(
n -> n % 2 == 0, // 外层:奇偶
Collectors.partitioningBy(n -> n > 6) // 内层:大小
));
System.out.println("偶数且>6: " + nested.get(true).get(true));
System.out.println("偶数且<=6: " + nested.get(true).get(false));
System.out.println("奇数且>6: " + nested.get(false).get(true));
System.out.println("奇数且<=6: " + nested.get(false).get(false));
}
}
partitioningBy 的优势:
- 语义明确:专门用于二元分组
- 性能优化:比
groupingBy更高效,因为只有两个键 - 结果可预测:返回的 Map 一定包含 true/false 两个键
- 支持下游收集器:可以进行复杂的二次处理
适用场景:
- 布尔条件的二元分类(是否、存在、满足等)
- 数据统计分析(分组统计、分组求值)
- 复杂业务规则的条件划分
注意事项:
- 返回的 Map 类型是
HashMap,不保证顺序 - 如果不需要下游收集器,直接使用即可
- 适合处理二元逻辑,多分类请使用
groupingBy
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播