Java 中将 List 中对象的某一列转换为 Set

在 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 以下可用 代码冗长

最佳实践建议

  1. 推荐使用 Stream API:代码简洁,可读性好

  2. 考虑使用 LinkedHashSet:如果需要保持顺序

  3. 总是处理 null 值:避免 NullPointerException

  4. 大数据量考虑并行流:但要注意线程安全问题

  5. 使用具体类型:明确指定 Set 的实现类型,便于维护

相关推荐
油丶酸萝卜别吃3 小时前
utils.js 说明文档
开发语言·javascript·ecmascript
rannn_1115 小时前
【力扣hot100】链表专题|160、206、234、141、142
java·算法·leetcode·链表·面试·开发
leisoo80976 小时前
100GBA股股票数据怎么存ClickHouseRedisMySQLJSON完整对比
大数据·linux·服务器·开发语言·python
不会代码的小猴6 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
IKUN家族7 小时前
Spring IoC&DI
java·spring·rpc
一只旭宝7 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
山荷枝8 小时前
03-框架--Spring
java·后端·spring
ChaHae-In9 小时前
SpringBoot统一功能处理
java·spring boot·后端
coder!mq9 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding9 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言