【Java集合】Set 接口 —— HashSet 与 TreeSet 详解

news2024/11/17 12:50:02

Set接口和List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格。与List接口不同的是,Set接口中的元素无序,并且都会以某种规则保证存入的元素不出现重复。

Set接口主要有两个实现类,分别是HashSet和TreeSet。其中,HashSet是根据对象的哈希值来确定元素在集合中的存储的位置,因此具有良好的存取和查找性能;TreeSet则是以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序。

HashSet集合

HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的。当向HashSet集合中添加一个元素时,首先会调用该元素的hashCode()方法来确定元素的存储位置,然后再调用元素对象的equals()方法来确保该位置没有重复元素。Set集合与List集合存取元素的方式都一样。

当调用HashSet集合的add()方法存入元素时,首先调用当前存入元素的hashCode()方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置。如果该位置上没有元素,则直接将元素存入,如果该位置上有元素存在,则会调用equals()方法让当前存入的元素依次和该位置上的元素进行比较,如果返回的结果为false就将该元素存入集合,返回的结果为true则说明有重复元素,就将该元素舍弃。整个存储的流程如图2所示。

class Student {
    private String id;
    private String name;
    public Student(String id, String name) { 
        this.id = id;
        this.name = name;
    }
      // 重写toString()方法
    public String toString() { 
        return id + ":" + name;
    }
      // 重写hashCode()方法
    public int hashCode() { 
        return id.hashCode();    // 返回id属性的哈希值
    }
      // 重写equals()方法
    public boolean equals(Object obj) { 
        if (this == obj) {     // 判断是否是同一个对象
            return true;       // 如果是,直接返回true
        }
        if (!(obj instanceof Student)) {     // 判断对象是为Student类型
            return false;       // 如果对象不是Student类型,返回false
        }
        Student stu = (Student) obj;          // 将对象强转为Student类型
         boolean b = this.id.equals(stu.id); // 判断id值是否相同
        return    b;                                 // 返回判断结果
    }

Student类重写了Object类的hashCode()和equals()方法。在hashCode()方法中返回id属性的哈希值,在equals()方法中比较对象的id是否相等,并返回结果。当调用HashSet集合的add()方法添加stu3对象时,发现它的哈希值与stu2对象相同,而且stu2.equals(stu3)返回true,HashSet集合认为两个对象相同,因此重复的Student对象被舍弃了。

TreeSet集合

TreeSet是Set接口的另一个实现类,它内部采用平衡二叉树来存储元素,这样的结构可以保证TreeSet集合中没有重复的元素,并且可以对元素进行排序。

图1 二叉树的存储结构

针对TreeSet集合存储元素的特殊性,TreeSet在继承Set接口的基础上实现了一些特有的方法,如表1所示。

表1 TreeSet集合的特有方法

方法声明

功能描述

Object first()

返回TreeSet集合的首个元素

Object last()

返回TreeSet集合的最后一个元素

Object lower(Object o)

返回TreeSet集合中小于给定元素的最大元素,如果没有返回null

Object floor(Object o)

返回TreeSet集合中小于或等于给定元素的最大元素,如果没有返回null

Object higher(Object o)

返回TreeSet集合中大于给定元素的最小元素,如果没有返回null

Object ceiling(Object o)

返回TreeSet集合中大于或等于给定元素的最小元素,如果没有返回null

Object pollFirst()

移除并返回集合的第一个元素

Object pollLast()

移除并返回集合的最后一个元素

集合中的元素在进行比较时,都会调用compareTo()方法,该方法是Comparable接口中定义的,因此要想对集合中的元素进行排序,就必须实现Comparable接口。Java中大部分的类都实现了Comparable接口,并默认实现了接口中的CompareTo()方法,如Integer、Double和String等。

为了解决这个问题,Java提供了两种TreeSet的排序规则,分别为:自然排序和定制排序。在默认情况下,TreeSet集合都是采用自然排序。

1.自然排序

自然排序要求向TreeSet集合中存储的元素所在类必须实现Comparable接口,并重写compareTo()方法,然后TreeSet集合就会对该类型元素使用compareTo()方法进行比较,并默认进行升序排序。

       public int compareTo(Object obj){
           Teacher s = (Teacher) obj;    
             // 定义比较方式,先比较年龄age,再比较名称name     
            if(this.age -s.age > 0) {        
                    return 1;
            }
            if(this.age -s.age == 0) {        
                return this.name.compareTo(s.name);    
            }
            return -1;
        }

2.定制排序

有时候,用户自定义的类型数据所在的类没有实现Comparable接口或者对于实现了Comparable接口的类而不想按照定义的compareTo()方法进行排序。例如,希望存储在TreeSet集合中的字符串可以按照长度而不是英文字母的顺序来进行排序,这时,可以通过在创建TreeSet集合时就自定义一个比较器来对元素进行定制排序。

    class MyComparator implements Comparator {  
        public int compare(Object obj1, Object obj2) {  // 定制排序方式
            String s1 = (String) obj1;
            String s2 = (String) obj2;
            int temp = s1.length() - s2.length();
            return temp;
        }
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot使用配置方式整合MyBatis

文章目录 一、实战目标二、步骤概览1. 创建部门映射器接口2. 创建映射器配置文件3. 配置全局映射器4. 测试映射器接口 三、详细步骤1、创建部门映射器接口2、创建映射器配置文件3、配置全局映射器4、测试映射器接口 四、结语 一、实战目标 在本实战课程中,我们将学…

ChatGPT高级语音助手正式上线!OpenAI:50多种语言、9种声线可选

①OpenAI终于要面向其所有付费用户开放ChatGPT的类人高级人工智能(AI)语音助手功能——“高级语音模式”(AVM); ②所有付费订阅ChatGPT Plus和Team计划的用户,都将可以使用新的AVM功能,不过该模…

qt P2P网络通信(tcp、udp)

一、TCP Qt中的TCP通信是基于Qt框架中的网络模块实现的,主要涉及到QTcpSocket和QTcpServer两个类。TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,适用于需要可靠传输的应用场景,如文件传输…

【实战篇】join语句怎么优化?

背景 在上一篇文章中,我们介绍了 join 语句的两种算法,分别是 Index Nested-Loop Join(NLJ) 和 Block Nested-Loop Join(BNL)。 我们发现在使用 NLJ 算法的时候,其实效果还是不错的,比通过应用层拆分成多个语句然后再拼接查询结…

数字化转型的理论指南:推动企业变革的全面路径

企业数字化转型的战略框架 在当今全球化的数字经济中,企业数字化转型已成为组织发展的核心战略。无论是初创公司还是跨国企业,成功的数字化转型不仅依赖于新技术的应用,还要求从战略到运营的全方位调整。这种转型不仅包括引入先进的技术&…

一键去水印小程序源码系统 下载无水印的高清图片 带完整的安装代码包以及搭建部署教程

系统概述 一键去水印小程序源码系统是一款专为图片去水印设计的软件开发包(SDK),它集成了先进的图像处理技术和智能识别算法,能够自动识别并去除图片中的水印,同时保持图片的高清画质不受损。该系统支持多种图片格式&…

树莓派4B配置教程 1

目录 树莓派初次入门 树莓派系统烧录 开启树莓派 为树莓派配置SSH和VNC远程服务 树莓派初次入门 笔者最近入门了树莓派4b,打算后续使用树莓派做点小东西玩玩。 新到手的树莓派,默认是一块白板,我们是需要使用到的有如下这些东西&#xf…

基于AWR1642 讲解TI毫米波雷达开发环境搭建

文章内容同步发布在公众号(雷达原理与系统),欢迎关注交流~ 这是第三篇文章,上一篇文章介绍了“TI官方资源介绍和使用”,感兴趣的可以去参考一下。本篇内容打算介绍基于AWR1642讲解TI毫米波雷达开发环境搭建,包括常用的…

24 基于51单片机的公交车报站仿真(LCD12864、DS1302、串口)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机,采用DS1302时钟模块读取时间,通过LCD12864显示实时时间,然后两个按键,一个按下表示到站,一个按下表示没到站。 到达站点&a…

亚信安全天穹5分钟勒索体检 免费试用今起上线

对于勒索攻击的认知 你是否还停留在“2.0时代”? 勒索攻击无疑是企业面临的最大威胁,2024年上半年,勒索组织数量同步增长超过50%,勒索攻击数量也持续攀升,平均勒索赎金突破520万美元。 当前,勒索攻击治理…

Spring Boot 进阶- 如何从配置文件中获取值?

&emps;在上一篇文章中,我们介绍了两种配置文件的方式,那么在添加完配置文件之后,我们如何从配置文件中获取到对应配置的值呢?这篇文章中我们就来看看这个问题。 一般的说SpringBoot中读取配置文件的方式有两种 @Value注解:基于@Value注解进行配置,一般适用于单个属性…

工业狗转行AI的心路历程,重新来过为时不晚!

言归正传,原本想写一篇人工智能大模型的科普文,为以后整理学习笔记开个头,但是细细琢磨了一下我这半吊子水平,怕是说不齐全。而且,我一直以来都很想跟把自己跨专业/行业转行AI的心路历程跟别人分享一下,希望…

10.1 Linux_并发_进程基本知识

进程和程序的区别: 程序是存放在磁盘上的文件,是静态的。进程就是跑起来的程序,是动态的。它包括创建、调度、执行、消亡。是一个程序所分配资源的总称。 具体提关系如下: 各部分具体含义参考博文"16.C基础_内存管理"…

双token无感刷新(vue3+node.js)

无感刷新的基本原理 使用刷新令牌(refresh token): ○ 应用程序在首次登录成功后会获得一个访问令牌(access token)和一个刷新令牌(refresh token)。 ○ 访问令牌通常有较短的有效期&#xff0…

2024史上最全网络安全面试题+答案,看完offe拿到手软!

1.1 网络安全行业现状 安全行业起步晚。安全行业整体起来才没几年,多数企业因为资源投入和建设时间原因导致覆盖面和深入度都不够,这其中甚至包括一些国内大厂,并没有想象的那么安全。其安全水位仅能应付一些白帽子级别,针对专业…

产品经理有必要学习大模型技术吗???

产品经理要讨论的,不是有没有必要学习大模型,而是以怎样的姿势拥抱大模型。 我之前公司是外企,还记得当年Iphone刚推出的时候,我的一个同事从东北老家拿着一个U盘跑到北京,跟我们公司部门主管描绘了他设想中PC端产品迁…

终于不用为GPU算力发愁了,FLUX LoRA训练一键启动!(附模型)

FLUX 是一个开源的全新的图像生成器,可以生成逼真的超现实图像,人们称它为 Midjourney 的终结者,下一代 Stable Diffusion 的替代品。 FLUX究竟强大到什么程度?外网到现在为止,都还有抵制它的声音。 Google DeepMind 团…

excel快速入门(二)

Excel的概念说明 文章目录 Excel的概念说明常见术语说明单元格/单元格区域活动单元格/单元格区域行或列单元格引用相对引用绝对引用混合引用 Excel的常见格式说明单元格格式数字格式 Excel 工作表编辑鼠标指针介绍1.白色十字状2.单向黑色箭头状3.双向单竖线箭头状4.双向双竖线箭…

Dubbo框架面试题

1.什么是Dubbo? Dubbo是基于Java的高性能轻量级的RPC分布式服务框架,现已成为 Apache 基金会孵化项目。 2.为什么要使用Dubbo? 随着互联网的快速发展,Web应用程序的规模不断扩大,分布式服务体系结构和流计算体系结构势在必行。 dubbo的…

对博客系统进行自动化测试

博客系统代码:spring-blog taotao/Studying JavaEE Advanced - 码云 - 开源中国 (gitee.com) 自动化脚本代码:BlogAutoTest taotao/Studying JavaEE Advanced - 码云 - 开源中国 (gitee.com) 上线项目地址:博客登陆页 目录 一、博客系统项…