Java Set集合 #

一、Set接口 #

1.1 特点 #

  • 不允许重复元素
  • 最多包含一个null元素
  • 没有索引

1.2 常用方法 #

java
Set<String> set = new HashSet<>();

// 添加
set.add("A");
set.add("B");

// 删除
set.remove("A");
set.clear();

// 判断
set.contains("A");
set.isEmpty();
set.size();

二、HashSet #

2.1 特点 #

  • 基于哈希表实现
  • 无序
  • 查找、添加、删除时间复杂度O(1)
  • 允许null元素

2.2 基本使用 #

java
Set<String> set = new HashSet<>();

// 添加
set.add("A");
set.add("B");
set.add("C");
set.add("A");  // 重复元素不会被添加

System.out.println(set);  // [A, B, C](顺序不确定)

// 删除
set.remove("B");

// 判断
System.out.println(set.contains("A"));  // true
System.out.println(set.contains("B"));  // false

// 遍历
for (String s : set) {
    System.out.println(s);
}

set.forEach(System.out::println);

2.3 自定义对象 #

java
public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && Objects.equals(name, person.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

// 使用
Set<Person> set = new HashSet<>();
set.add(new Person("张三", 25));
set.add(new Person("张三", 25));  // 不会重复添加
System.out.println(set.size());  // 1

三、LinkedHashSet #

3.1 特点 #

  • 基于哈希表和链表实现
  • 保持插入顺序
  • 性能略低于HashSet

3.2 基本使用 #

java
Set<String> set = new LinkedHashSet<>();

set.add("C");
set.add("A");
set.add("B");

System.out.println(set);  // [C, A, B](保持插入顺序)

3.3 应用场景 #

java
// 去重并保持顺序
List<String> list = Arrays.asList("A", "B", "A", "C", "B");
Set<String> set = new LinkedHashSet<>(list);
System.out.println(set);  // [A, B, C]

四、TreeSet #

4.1 特点 #

  • 基于红黑树实现
  • 元素自然排序
  • 不允许null元素

4.2 基本使用 #

java
Set<Integer> set = new TreeSet<>();

set.add(5);
set.add(1);
set.add(3);
set.add(2);

System.out.println(set);  // [1, 2, 3, 5](自然排序)

// 字符串排序
Set<String> strings = new TreeSet<>();
strings.add("C");
strings.add("A");
strings.add("B");
System.out.println(strings);  // [A, B, C]

4.3 自定义排序 #

java
// 使用Comparator
Set<Integer> set = new TreeSet<>((a, b) -> b - a);  // 降序
set.add(5);
set.add(1);
set.add(3);
System.out.println(set);  // [5, 3, 1]

// 对象排序
Set<Person> persons = new TreeSet<>(Comparator.comparing(Person::getAge));
persons.add(new Person("张三", 25));
persons.add(new Person("李四", 20));

4.4 NavigableSet方法 #

java
TreeSet<Integer> set = new TreeSet<>(Arrays.asList(1, 3, 5, 7, 9));

// 查找
System.out.println(set.first());        // 1
System.out.println(set.last());         // 9
System.out.println(set.lower(5));       // 3(小于5的最大值)
System.out.println(set.higher(5));      // 7(大于5的最小值)
System.out.println(set.floor(5));       // 5(小于等于5的最大值)
System.out.println(set.ceiling(5));     // 5(大于等于5的最小值)

// 子集
System.out.println(set.headSet(5));     // [1, 3](小于5)
System.out.println(set.tailSet(5));     // [5, 7, 9](大于等于5)
System.out.println(set.subSet(3, 7));   // [3, 5]([3, 7))

五、Set实现类对比 #

实现 底层 排序 性能 null
HashSet 哈希表 无序 最高 允许
LinkedHashSet 哈希表+链表 插入顺序 较高 允许
TreeSet 红黑树 自然排序 较低 不允许

六、常用操作 #

6.1 去重 #

java
// List去重
List<Integer> list = Arrays.asList(1, 2, 2, 3, 3, 3);
Set<Integer> set = new HashSet<>(list);
System.out.println(set);  // [1, 2, 3]

// 保持顺序去重
Set<Integer> linkedSet = new LinkedHashSet<>(list);
System.out.println(linkedSet);  // [1, 2, 3]

6.2 集合运算 #

java
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3));
Set<Integer> set2 = new HashSet<>(Arrays.asList(2, 3, 4));

// 并集
Set<Integer> union = new HashSet<>(set1);
union.addAll(set2);
System.out.println(union);  // [1, 2, 3, 4]

// 交集
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
System.out.println(intersection);  // [2, 3]

// 差集
Set<Integer> difference = new HashSet<>(set1);
difference.removeAll(set2);
System.out.println(difference);  // [1]

6.3 判断子集 #

java
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3));
Set<Integer> set2 = new HashSet<>(Arrays.asList(1, 2));

System.out.println(set1.containsAll(set2));  // true(set2是set1的子集)

七、总结 #

实现 使用场景
HashSet 快速查找,不关心顺序
LinkedHashSet 需要保持插入顺序
TreeSet 需要排序

Set要点:

  • HashSet最快但无序
  • LinkedHashSet保持插入顺序
  • TreeSet自动排序
  • 自定义对象需要重写equals和hashCode
最后更新:2026-03-26