实现Set接口的HashSet

HashSet 的底层实现实际上依赖于 HashMap,而 HashMap 的底层结构确实是 数组+链表+红黑树 的组合。

在这里插入图片描述
存储过程

  1. 计算哈希值: 当向 HashSet 添加一个元素时,首先会使用该元素的 hashCode() 方法计算其哈希值。
    这个哈希值是一个整数,代表了元素在哈希表中的位置。
  2. 确定数组索引: 然后,哈希值会被进一步处理以确定元素应该存储在数组的哪个索引位置。通常,这个过程包括取模运算,例如:
    int index = hashCode % array.length;
    这样可以确保哈希值被转化为有效的数组索引。
  3. 处理哈希冲突: 如果两个不同的元素计算出的索引相同(即发生哈希冲突),HashSet 会在该索引位置使用链表(或在 Java 8 之后可能使用红黑树)来存储这些冲突的元素。 例如,如果 A 和 B 的哈希值都映射到数组索引 2,那么 B 会被添加到 A所在链表的后面。

当向 HashSet 中添加重复的元素时,HashSet 会检测到并拒绝添加该元素。具体来说,这是通过以下几个步骤实现的:

  1. 计算哈希值: 首先,计算新元素的哈希值。
  2. 确定数组索引: 使用哈希值确定该元素应该存储在数组中的哪个索引位置。
  3. 查找冲突链表: 在确定的索引位置上,检查是否已经存在一个链表或树结构。
  4. 比较元素: 遍历链表或树结构,使用 equals 方法比较新元素和已存在的每个元素。 如果发现有一个元素与新元素相等(equals方法返回 true),则认为新元素已经存在于 HashSet 中,不会将其添加。

基本使用:

package study;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

public class Collection_Set {
    public static void main(String[] args) {
        /*
            Iterable<E> (接口)
                   ↑
            Collection<E> (接口) - 继承自 Iterable<E>
                   ↑
            Set<E> (接口) - 继承自 Collection<E>
                   ↑
            AbstractCollection<E> (抽象类) - 部分实现 Collection<E>
                   ↑
            AbstractSet<E> (抽象类) - 继承自 AbstractCollection<E> 并部分实现 Set<E>
                   ↑
            HashSet<E> (类) - 继承自 AbstractSet<E> 并实现 Set<E> 和 Collection<E>

            HashSet 类除了实现 Set 接口的方法外,还提供了一些独有的方法。这些方法在 Set<> set 中无法直接使用:
            clone(): 创建并返回此 HashSet 的浅表副本。
            spliterator(): 创建一个后期绑定且故障迅速的 Spliterator,用于遍历此 Set 中的元素。

            HashSet 内部使用 HashMap 来存储其元素。
        */
        // TODO 集合 - Collection - Set
        // HashSet: Hash + Set
        // Hash: 哈希算法,散列算法
        // TODO 增加数据
        HashSet set = new HashSet();
//        set.add("zhangsan");
//        set.add("zhangsan");
//        set.add("lisi");
//        set.add("wangwu");
        set.addAll(Arrays.asList("zhangsan", "lisi", "wangwu"));

        Object[] array = set.toArray();
        System.out.println(array);    // 打印数组中元素的类型和哈希码
        for (Object item : array)   // 打印数组中的元素
            System.out.println(item); // 这会调用每个元素的 toString() 方法
        System.out.println(Arrays.toString(array));  // 使用 Arrays.toString() 打印数组内容
        System.out.println(set);
        // [lisi, zhangsan, wangwu]
        // 会发现打印顺序和存储顺序不一样

        // TODO 修改数据 ,先删除数据再增加

        // TODO 删除数据
        // set.remove("wangwu");

        // TODO 查询数据
        for (Object o : set) {
            System.out.println(o);
        }
        System.out.println(set.isEmpty());
        System.out.println(set.contains("lisi"));
        System.out.println(set.size());
        Object clone_set = set.clone();
        System.out.println(clone_set);

    }
}

实践任务:创建一个程序,使用HashSet去除重复的元素

package study;

import java.util.HashSet;

public class day01_Collection_Set_进阶 {
    public static void main(String[] args) {
        // 在不指定泛型类型参数时,集合类被视为原始类型,可以存储任何类型的对象,但没有编译时的类型安全保障
        HashSet set = new HashSet();

        User user1 = new User();
        user1.id = 1001;
        user1.name = "zhangsan";
        User user2 = new User();
        user2.id = 1001;
        user2.name = "zhangsan";
        User user3 = new User();
        user3.id = 1003;
        user3.name = "wangwu";

        set.add(user1);
        set.add(user2);
        set.add(user3);

        System.out.println(set);  // 只是属性指一样,HashSet并不认为user1和user2是一样的
        // [User [id=1001, name=zhangsan], User [id=1001, name=zhangsan], User [id=1003, name=wangwu]]

        System.out.println(user1.hashCode());  // 990368553 可以简单类比成对象在内存中的地址
        System.out.println(user2.hashCode()); // 1096979270

        HashSet set1 = new HashSet();
        User1 user4 = new User1();
        user4.id = 1001;
        user4.name = "zhangsan";
        User1 user5 = new User1();
        user5.id = 1001;
        user5.name = "zhangsan";
        User1 user6 = new User1();
        user6.id = 1003;
        user6.name = "wangwu";

        set1.add(user4);
        set1.add(user5);
        set1.add(user6);

        System.out.println(set1);
        // [User1 [id=1001, name=zhangsan], User1 [id=1003, name=wangwu]]


    }
}

class User {
    public int id;
    public String name;

    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + "]";
    }
}

class User1 {
    public int id;
    public String name;

    @Override
    // 类似于内存地址
    // 如果HashCode相同,在HashSet计算元素存储的数组索引时,就会相同
    public int hashCode() {
//        return super.hashCode();
        return id;
    }

    @Override
    // 当HashSet计算元素存储的数组索引时相同,就会用这个equals函数来判断这两个元素是否相同
    public boolean equals(Object obj) {
//        return super.equals(obj);
        // instanceof 操作符用于测试一个对象是否是一个特定类的实例,或者是该类的子类的实例
        if (obj instanceof User1) {  // 保证要比较的类型相同
            User1 otherUser = (User1) obj;  //强制类型转换
            if (otherUser.id == this.id && otherUser.name.equals(this.name)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return "User1 [id=" + id + ", name=" + name + "]";
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/758813.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

idea乱码问题解决

乱码问题产生的根本原因 数据的编码和解码使用的不是同一个字符集 使用了不支持某个语言文字的字符集 Tomcat控制台乱码 在tomcat10.1.7这个版本中,修改 tomcat/conf/logging.properties中,所有的UTF-8为GBK即可 sout乱码问题,设置JVM加载.class文件时使用UTF-8字符集 设置虚…

我重生了,学会了珂朵莉树

还玩线段树吗&#xff1f; 前言&注明 我好像一万年没更新了&#xff1f; 化学&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff…

深度学习笔记: 最详尽解释逻辑回归 Logistic Regression

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家&#xff01; 逻辑回归概述 逻辑回归类似于线性回归&#xff0c;但预测的是某事物是否为真&#xff0c;而不是像大小这…

数字化那点事:一文读懂数字乡村

一、数字乡村的定义 数字乡村是指利用信息技术和数字化手段&#xff0c;推动乡村社会经济发展和治理模式变革&#xff0c;提升乡村治理能力和公共服务水平&#xff0c;实现乡村全面振兴的一种新型发展模式。它包括农业生产的数字化、乡村治理的智能化、乡村生活的现代化等方面…

【ai】trition:tritonclient.utils.shared_memory 仅支持linux

Can’t find tritonclient.utils.shared_memory on WIN10 #4149yolov4的python客户端 导入以后,windows 的pycharm 就是看不到折腾了很久:SaviorEnv 环境下安装tritonclient[all]也会失败 (base) C:\Users\zhangbin>conda create -n SaviorEnv python=3.8 Collecting pack…

信号与系统-实验5 离散时间系统的时域分析

一、实验目的 1、理解离散信号的定义与时域特征&#xff0c;掌握在时域求解信号的各种变换运算&#xff1b; 2、掌握离散系统的单位响应及其 MATLAB 实现的方法&#xff1b; 3、掌握离散时间序列卷积及其 MATLAB 实现的方法&#xff1b; 4、掌握利用 MATLAB 求解微分方程&a…

MySQL高级-MVCC-undo log 版本链

文章目录 1、undo log2、undo log 版本链2.1、然后&#xff0c;有四个并发事务同时在访问这张表。2.1.1、修改id为30记录&#xff0c;age改为32.1.2、修改id为30记录&#xff0c;name改为A32.1.3、修改id为30记录&#xff0c;age改为10 2.2、总结 1、undo log 回滚日志&#xf…

2.WeBASE一键部署

一、官方文档 一键部署可以在 同机 快速搭建WeBASE管理台环境&#xff0c;方便用户快速体验WeBASE管理平台。 一键部署会搭建&#xff1a;节点&#xff08;FISCO-BCOS 2.0&#xff09;、管理平台&#xff08;WeBASE-Web&#xff09;、节点管理子系统&#xff08;WeBASE-Node-…

单片机学习(14)--DS18B20温度传感器

DS18B20温度传感器 13.1DS18B20温度传感器基础知识1.DS18B20介绍2.引脚及应用电路3.内部结构框图4.存储器框图5.单总线介绍6.单总线电路规范7.单总线时序结构8.DS18B20操作流程9.DS18B20数据帧 13.2DS18B20温度读取和温度报警器代码1.DS18B20温度读取&#xff08;1&#xff09;…

Keil汇编相关知识

一、汇编的组成 1.汇编指令&#xff1a;在内存中占用内存&#xff0c;执行一条汇编指令会让处理器进行相关运算 分类&#xff1a;数据处理指令&#xff0c;跳转指令&#xff0c;内存读写指令&#xff0c;状态寄存器传送指令&#xff0c;软中断产生指令&#xff0c;协助处理器…

项目菜单配置

stores/index.js import {createStore } from "vuex"; //计算高度 let height window.innerHeight;//计算分辨率 let width window.innerWidth;let activeIndex localStorage.getItem("activeIndex"); if (activeIndex null || activeIndex "&q…

基于单片机技术的按键扫描电路分析

摘 要&#xff1a; 单片机应用技术被广泛应用于各种智能控制系统中&#xff0c;是电子信息类专业学生必修的一门专业课。在单片机端口信息输入模块中&#xff0c;按键是主要元器件之一&#xff0c;笔者主要介绍矩阵键盘的电路设计及控制程序编写&#xff0c;分析了单片机端口连…

商城自动化测试实战 —— 登录+滑块验证

hello大家好&#xff0c;我是你们的小编&#xff01; 本商城测试项目采取PO模型和数据分离式架构&#xff0c;采用pytestseleniumjenkins结合的方式进行脚本编写与运行&#xff0c;项目架构如下&#xff1a; 1、创建项目名称&#xff1a;code_shopping&#xff0c;创建所需项目…

springboot是否可以代替spring

Spring Boot不能直接代替Spring&#xff0c;但它是Spring框架的一个扩展和增强&#xff0c;提供了更加便捷和高效的开发体验。以下是关于Spring Boot和Spring关系的详细解释&#xff1a; Spring框架&#xff1a; Spring是一个广泛应用的开源Java框架&#xff0c;提供了一系列模…

Linux 2-Vim使用

1 什么是vi及vim&#xff1f; vi是文本编辑器&#xff1b;vim是程序开发工具。 2 vi的几种模式 1 一般模式&#xff1a;vi <fileName> 就进入命令模式&#xff0c;可以删除或者复制粘贴 2 编辑模式&#xff1a;修改内容 3 命令行模式&#xff1a;最下面一行&#xf…

追觅科技25届校招校招24年社招科技北森题库商业推理综合测评答题攻略、通关技巧

一、追觅科技这家公司怎么样&#xff1f; 追觅科技是一家在智能清洁家电领域表现出色的企业。 二、追觅科技待遇怎么样 追觅科技的待遇在业内具有竞争力&#xff0c;具体信息如下&#xff1a; 1. **薪酬结构**&#xff1a;根据对外经济贸易大学招生就业处发布的2023届校园招…

一、安装VMware16

本篇来源&#xff1a;山海同行 本篇地址&#xff1a;https://shanhaigo.cn/courseDetail/1805875642621952000 本篇资源&#xff1a;以整理到-山海同行 一、VMware虚拟机下载 1. 官网下载 1. 打开官网 打开VMware官网地址&#xff1a;https://www.vmware.com/ 2. 选择下载产…

ctfshow sqli-labs web532--web540

web532 时间盲注 admin")闭合 import requestsurl"https://8b83d32c-8348-4393-ad72-08d00f7f6cd0.challenge.ctf.show/" flag"" i0 while True:i 1low 32high 127while low < high:mid (lowhigh)//2#payloadf"if((ascii(substr((databas…

大语言模型(LLMs)全面学习指南,初学者入门,一看就懂!

大语言模型&#xff08;LLMs&#xff09;作为人工智能&#xff08;AI&#xff09;领域的一项突破性发展&#xff0c;已经改变了自然语言处理&#xff08;NLP&#xff09;和机器学习&#xff08;ML&#xff09;应用的面貌。这些模型&#xff0c;包括OpenAI的GPT-4o和Google的gem…

kafka(一)原理(2)组件

一、broker 1、介绍 kafka服务器的官方名字&#xff0c;一个集群由多个broker组成&#xff0c;一个broker可以容纳多个topic。 2、工作流程 3、重要参数 参数名称 描述 replica.lag.time.max.ms ISR中&#xff0c;如果Follower长时间未向Leader发送通信请求或同步数据&a…