在 Java 中将 List 中对象的某一列转换为 Set,有几种常用方法:
1. 使用 Stream API(最常用)
import java.util.*; import java.util.stream.Collectors; // 示例类 class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } public class Main { public static void main(String[] args) { List<Person> personList = Arrays.asList( new Person("张三", 25), new Person("李四", 30), new Person("王五", 25), new Person("张三", 28) // 重复的张三 ); // 方法1:提取 name 列到 Set(自动去重) Set<String> nameSet = personList.stream() .map(Person::getName) // 提取 name .collect(Collectors.toSet()); System.out.println(nameSet); // [张三, 李四, 王五] // 方法2:提取 age 列到 Set Set<Integer> ageSet = personList.stream() .map(Person::getAge) .collect(Collectors.toSet()); System.out.println(ageSet); // [25, 30, 28] } }2. 指定具体的 Set 实现
// 使用 HashSet Set<String> nameSet = personList.stream() .map(Person::getName) .collect(Collectors.toCollection(HashSet::new)); // 使用 TreeSet(排序) Set<String> sortedNameSet = personList.stream() .map(Person::getName) .collect(Collectors.toCollection(TreeSet::new)); // 使用 LinkedHashSet(保持插入顺序) Set<String> linkedNameSet = personList.stream() .map(Person::getName) .collect(Collectors.toCollection(LinkedHashSet::new));3. 处理可能为 null 的情况
// 方法1:过滤掉 null Set<String> nameSet = personList.stream() .map(Person::getName) .filter(Objects::nonNull) // 过滤 null .collect(Collectors.toSet()); // 方法2:使用 filter 和 Optional Set<String> nameSet = personList.stream() .map(Person::getName) .filter(name -> name != null && !name.trim().isEmpty()) // 过滤 null 和空字符串 .collect(Collectors.toSet());4. 复杂对象属性提取
// 如果属性是嵌套对象 class Department { private String deptName; // getters and setters } class Employee { private String name; private Department department; // getters and setters } // 提取嵌套属性 Set<String> deptNames = employeeList.stream() .map(Employee::getDepartment) .filter(Objects::nonNull) .map(Department::getDeptName) .collect(Collectors.toSet());5. 并行流处理(大数据量时)
Set<String> nameSet = personList.parallelStream() // 并行处理 .map(Person::getName) .collect(Collectors.toSet());6. 传统方法(不使用 Stream)
// 传统 for 循环 Set<String> nameSet = new HashSet<>(); for (Person person : personList) { nameSet.add(person.getName()); } // 传统 for 循环,处理 null Set<String> nameSet = new HashSet<>(); for (Person person : personList) { if (person.getName() != null) { nameSet.add(person.getName()); } }主要区别对比
方法 | 优点 | 缺点 |
|---|---|---|
Stream API | 代码简洁,可读性好,支持链式调用 | Java 8+ |
并行流 | 大数据量性能好 | 线程安全需注意 |
传统循环 | 兼容性好,Java 8 以下可用 | 代码冗长 |
最佳实践建议
推荐使用 Stream API:代码简洁,可读性好
考虑使用 LinkedHashSet:如果需要保持顺序
总是处理 null 值:避免 NullPointerException
大数据量考虑并行流:但要注意线程安全问题
使用具体类型:明确指定 Set 的实现类型,便于维护