0

0

如何在Java中使用HashSet存储唯一元素

P粉602998670

P粉602998670

发布时间:2025-09-18 14:24:02

|

629人浏览过

|

来源于php中文网

原创

HashSet通过哈希表实现元素唯一性,添加元素时自动去重,适用于快速查找、去重及集合操作,但需重写自定义类的hashCode与equals方法以确保正确性。

如何在java中使用hashset存储唯一元素

Java中要存储唯一元素,

HashSet
无疑是首选,它通过其内部的哈希机制确保了集合中不会出现重复项。你只需要将元素添加到
HashSet
中,它就会自动处理去重逻辑。

解决方案

HashSet
是Java集合框架中
Set
接口的一个实现,它底层基于哈希表(
HashMap
)实现。当你向
HashSet
中添加一个元素时,它会先计算该元素的哈希码(
hashCode()
方法),然后根据哈希码找到存储位置。接着,它会检查该位置是否已经存在一个与新元素“相等”(
equals()
方法)的元素。如果存在,新元素就不会被添加进来;如果不存在,新元素才会被成功加入。这个过程是自动且高效的。

这里有个简单的例子,展示了

HashSet
如何工作:

import java.util.HashSet;
import java.util.Set;

public class UniqueElementsExample {
    public static void main(String[] args) {
        Set uniqueNames = new HashSet<>();

        System.out.println("尝试添加元素...");
        // 添加一些字符串
        System.out.println("添加 'Alice': " + uniqueNames.add("Alice")); // 第一次添加,通常返回true
        System.out.println("添加 'Bob': " + uniqueNames.add("Bob"));
        System.out.println("添加 'Alice' (重复): " + uniqueNames.add("Alice")); // 重复添加,返回false
        System.out.println("添加 'Charlie': " + uniqueNames.add("Charlie"));
        System.out.println("添加 'Bob' (重复): " + uniqueNames.add("Bob")); // 重复添加,返回false

        System.out.println("\nHashSet中的唯一元素:");
        for (String name : uniqueNames) {
            System.out.println(name);
        }

        System.out.println("\nHashSet的大小: " + uniqueNames.size()); // 预期大小为3
    }
}

运行这段代码,你会发现输出结果中“Alice”和“Bob”只出现了一次,

HashSet
的大小也是3,而不是5。这正是
HashSet
的魅力所在,它在后台默默地为你处理了元素的唯一性。

立即学习Java免费学习笔记(深入)”;

自定义对象在HashSet中如何保证唯一性?

对于像

String
Integer
这类Java内置类型,它们已经正确地重写了
hashCode()
equals()
方法,所以直接放入
HashSet
就能保证唯一性。但当我们处理自定义对象时,情况就有些不同了。如果你直接将自定义对象放入
HashSet
,很可能会发现即使内容完全相同的两个对象也被视为不同的元素,因为
Object
类默认的
hashCode()
equals()
方法是基于对象的内存地址来判断的。

要让

HashSet
正确识别自定义对象的唯一性,你必须在自定义类中重写
hashCode()
equals()
方法。这是Java中一个非常重要的契约:如果两个对象
equals()
返回
true
,那么它们的
hashCode()
值必须相同。反之,如果
hashCode()
值相同,
equals()
不一定返回
true
(这会导致哈希冲突,但仍能通过
equals
判断唯一性)。

举个例子,假设我们有一个

Person
类:

Vondy
Vondy

下一代AI应用平台,汇集了一流的工具/应用程序

下载
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;
    }

    @Override
    public String toString() {
        return "Person{" +
               "name='" + name + '\'' +
               ", age=" + age +
               '}';
    }

    // 默认情况下,HashSet会认为两个内容相同的Person对象是不同的
    // 因为它们在内存中的地址不同。
    // 必须重写hashCode()和equals()
    @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 && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        // 通常使用Objects.hash()来生成哈希码,它会综合考虑所有参与equals比较的字段
        return java.util.Objects.hash(name, age);
    }
}

在上面的

Person
类中,我们重写了
equals()
hashCode()
equals()
方法现在会比较
name
age
字段是否相同,而
hashCode()
则会基于这两个字段生成一个哈希码。这样,当
HashSet
处理
Person
对象时,它就能正确地判断两个
Person
对象是否“相等”,从而保证了集合中
Person
对象的唯一性。

如果你忘记重写或者重写不当,比如只重写了

equals()
而没有重写
hashCode()
,那么程序在运行时可能会出现意想不到的行为,甚至导致
HashSet
无法正常工作,因为哈希码的冲突处理机制会失效。所以,这两个方法总是应该一起重写,并且遵循它们之间的契约。

HashSet的性能特点和适用场景是什么?

HashSet
以其出色的性能,在许多场景下都表现得游刃有余。它的核心优势在于查找、添加和删除操作的平均时间复杂度都是O(1)。这意味着无论集合中有多少元素,这些操作的耗时理论上都是常数级别的,非常快。当然,这是在没有大量哈希冲突的理想情况下。如果哈希函数设计不佳导致大量冲突,最坏情况下性能可能会退化到O(n)。

性能特点:

  • 快速查找、添加、删除: 平均O(1)时间复杂度,这得益于哈希表的数据结构。
  • 无序性:
    HashSet
    不保证元素的存储顺序,你不能指望迭代时元素会按照添加的顺序或者任何特定顺序出现。
  • 非线程安全:
    HashSet
    不是线程安全的。在多线程环境下,如果多个线程同时修改
    HashSet
    ,可能会导致数据不一致或运行时错误。如果需要线程安全,可以使用
    Collections.synchronizedSet(new HashSet<>())
    java.util.concurrent.ConcurrentHashMap
    的键集(
    keySet()
    )。
  • 空间换时间: 为了实现O(1)的平均时间复杂度,
    HashSet
    通常会占用比
    ArrayList
    更多的内存空间,因为它需要存储哈希表结构以及可能存在的空槽。

适用场景:

  • 去重: 这是
    HashSet
    最典型的应用。当你有一个包含重复元素的列表,想快速得到一个只包含唯一元素的新列表时,
    HashSet
    是最佳选择。
    List rawList = Arrays.asList("apple", "banana", "apple", "orange", "banana");
    Set uniqueItems = new HashSet<>(rawList); // 快速去重
    System.out.println(uniqueItems); // 输出: [orange, banana, apple] (顺序不确定)
  • 快速判断元素是否存在: 如果你需要频繁地检查某个元素是否在集合中,
    HashSet
    contains()
    方法效率极高。
    Set dictionary = new HashSet<>(Arrays.asList("cat", "dog", "bird"));
    boolean found = dictionary.contains("dog"); // O(1)查找
  • 实现缓存: 比如,记录已经处理过的ID,避免重复处理。
  • 数学集合操作: 比如计算两个集合的交集、并集、差集,
    HashSet
    提供了便捷的方法(如
    retainAll()
    ,
    addAll()
    ,
    removeAll()
    )。

总的来说,当你关注元素的唯一性,并且需要对元素进行快速的添加、删除和查找操作,同时对元素的顺序没有要求时,

HashSet
是一个非常强大且高效的选择。理解它的工作原理,尤其是
hashCode()
equals()
的契约,能帮助你更好地驾驭它,避免在处理自定义对象时踩坑。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

831

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

737

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

733

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16925

2023.08.03

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

10

2026.01.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.4万人学习

C# 教程
C# 教程

共94课时 | 6.5万人学习

Java 教程
Java 教程

共578课时 | 45.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号