登录
首页 >  文章 >  java教程

JavaSet接口特性及去重原理解析

时间:2026-02-08 11:18:41 359浏览 收藏

从现在开始,努力学习吧!本文《Java Set接口特点及不重复说明》主要讲解了等等相关知识点,我会在golang学习网中持续更新相关的系列文章,欢迎大家关注并积极留言建议。下面就先一起来看一下本篇正文内容吧,希望能帮到你!

Set接口保证元素不重复但不保证顺序;HashSet依赖hashCode()和equals()去重,需同步重写且避免可变字段;TreeSet要求元素可比较,否则运行时抛ClassCastException;LinkedHashSet保持插入顺序但内存开销更大。

在Java里Set接口有什么特点_Java不重复集合说明

Set 接口保证元素不重复,但不保证顺序

Java 的 Set 接口核心语义就是「无序、不重复」。它不继承 List,所以没有索引访问(get(int))、不能存重复元素(add() 返回 false 表示已存在),也不承诺遍历顺序——这点和 HashSetLinkedHashSetTreeSet 的具体实现强相关。

HashSet 用哈希码去重,但要求正确重写 equals() 和 hashCode()

最常用的实现 HashSet 依赖对象的 hashCode()equals() 判断是否重复。如果只重写 equals() 却没同步改 hashCode(),会出现「两个逻辑相等的对象能同时加进 Set」的诡异现象。

常见错误场景:

  • 自定义类(如 Person)没重写 hashCode(),仅靠 equals() 判断相等 → Set 无法识别重复
  • 重写了 hashCode() 但用了可变字段(比如 name 可被修改),之后又修改该字段 → 对象可能从 Set 中「消失」,再也 contains() 不到
public class Person {
    private String name;
    private int age;

    // 必须同时重写!且字段都参与计算
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age); // 用相同字段
    }
}

TreeSet 要求元素可比较,否则运行时报 ClassCastException

TreeSet 是基于红黑树的有序 Set,它要么要求元素实现 Comparable 接口(如 StringInteger),要么在构造时传入 Comparator。否则往里加对象会直接抛 ClassCastException,不是编译错,是运行时错。

典型踩坑点:

  • 往空的 TreeSet 里 add 自定义对象,但 Person 没实现 Comparable,也没传 Comparator
  • 用了 Comparator,但比较逻辑返回 0 的条件和 equals() 不一致 → Set 去重行为和预期不符

LinkedHashSet 记住插入顺序,但内存开销略大

LinkedHashSetHashSet 基础上加了双向链表,所以迭代顺序 = 插入顺序。适合需要「去重 + 保持添加顺序」的场景,比如去重日志、过滤重复请求 ID 并按时间排列。

但它比 HashSet 多维护链表指针,每个元素多占约 8–16 字节内存;插入和删除也稍慢一点。如果不需要顺序,别默认选它。

注意:LinkedHashSet 的「顺序」只反映插入顺序,和 hashCode 或内容无关;它也不支持按访问顺序排序(那是 LinkedHashMap 的事)。

真正容易被忽略的是:Set 的「不重复」完全由具体实现类的行为决定,而不是接口本身强制约束。比如你写个错误的 hashCode()HashSet 就失效;而 TreeSet 的「重复」判断甚至和 equals() 无关,只看 compareTo() 是否返回 0。

理论要掌握,实操不能落!以上关于《JavaSet接口特性及去重原理解析》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>