Java中HashSet、LinkedHashSet和TreeSet的底层原理

HashSet

Java中的HashSet的底层原理主要基于哈希表(HashMap)来实现。以下是HashSet底层原理的简要总结:
数据结构:

HashSet内部使用哈希表(实际上是一个HashMap的实例)来存储元素。哈希表由一个数组(桶)和多个链表(或红黑树,在Java 8及以后版本中,当链表长度超过某个阈值时,会转换为红黑树)组成。

哈希函数

当向HashSet中添加元素时,首先会计算该元素的哈希码(通过调用对象的hashCode()方法)。哈希码是一个整数,用于确定元素在哈希表中的位置。
使用哈希码和哈希表的大小(即桶的数量)来计算元素应该存放在哪个桶中。这通常是通过哈希码与哈希表大小取模(hash % size)来实现的。

存储元素:

如果计算出的桶是空的,那么该元素就直接存放在这个桶中。
如果计算出的桶已经包含了一个或多个元素(即哈希冲突),那么这些元素会形成一个链表(或红黑树),并将新元素添加到链表的末尾(或红黑树中)。

查找元素:

当从HashSet中检索元素时,也会首先计算该元素的哈希码,然后使用哈希码来确定应该查找哪个桶。
接着,在对应的桶中遍历链表(或红黑树)来查找是否存在相同的元素。由于哈希码相同的元素被存放在同一个桶中,因此需要遍历链表(或红黑树)来找到具体的元素。

处理哈希冲突:

哈希冲突是指不同的元素具有相同的哈希码。HashSet使用链表(或红黑树)来处理哈希冲突,即将哈希码相同的元素存放在同一个链表(或红黑树)中。

动态扩容:

当哈希表中的元素数量达到某个阈值时(通常是哈希表大小的某个比例,如0.75),哈希表会自动扩容,以减小哈希冲突的可能性。扩容通常是通过创建一个新的、更大的哈希表,并将原哈希表中的元素重新分配到新的哈希表中来实现的。

无序性:

HashSet不保证元素的迭代顺序与插入顺序相同。这是因为元素在哈希表中的位置取决于其哈希码,而哈希码的计算与元素的插入顺序无关。

总之,HashSet通过哈希表和哈希函数实现了快速添加、删除和查找元素的功能,并且支持动态扩容来处理哈希冲突和保持性能。

LinkedHashSet

Java中的LinkedHashSet的底层原理主要基于HashMap和双向链表(doubly linked list)来实现。以下是对LinkedHashSet底层原理的简要总结:
数据结构:

LinkedHashSet内部使用一个特殊的HashMap实例(实际上是LinkedHashMap)来存储元素。这个HashMap不仅保存了键值对信息,还通过双向链表维护了元素的插入顺序。

双向链表:

与普通的HashMap不同,LinkedHashMap在HashMap的基础上增加了一个双向链表。这个双向链表用于维护元素的插入顺序(或访问顺序,取决于LinkedHashMap的构造参数)。
每个在LinkedHashMap中的节点(即Entry对象)都包含指向其前一个节点和后一个节点的指针(before和after属性),从而形成一个双向链表。

哈希表与双向链表的结合:

在LinkedHashSet中,元素的存储和查找主要通过哈希表来实现,以提供快速的插入、删除和查找操作。
同时,双向链表则用于维护元素的插入顺序。当元素被添加到LinkedHashSet时,它会被添加到双向链表的尾部(或头部,取决于LinkedHashMap的访问顺序策略)。

迭代顺序:

由于LinkedHashSet维护了元素的插入顺序,因此其迭代器(iterator)会按照元素的插入顺序进行遍历。这是通过遍历底层双向链表来实现的。

性能特点:

LinkedHashSet的插入、删除和查找操作的平均时间复杂度都是O(1),这与普通的HashSet相同。但是,由于LinkedHashSet需要维护双向链表,因此在内存使用上可能会稍高于HashSet。
另一方面,由于LinkedHashSet提供了有序的迭代顺序,因此在某些需要保持元素顺序的场景下,使用LinkedHashSet可能会更加方便。

继承关系:

LinkedHashSet继承自HashSet,并实现了Set接口。它的底层实现依赖于LinkedHashMap,因此LinkedHashSet在方法操作上与HashSet相同,但在迭代顺序上有所不同。

总的来说,LinkedHashSet通过结合哈希表和双向链表的结构,实现了具有可预知迭代顺序的集合。

TreeSet

Java中的TreeSet底层原理主要基于红黑树(Red-Black Tree)数据结构来实现。以下是TreeSet的底层原理的简要总结:
数据结构:

TreeSet使用红黑树作为其内部的数据结构。红黑树是一种自平衡的二叉搜索树,它能够在添加、删除和查找元素时保持较好的性能。

元素排序:

TreeSet中的元素按照其自然顺序(如果元素实现了Comparable接口)或根据提供的Comparator对象进行排序。默认情况下,元素按照升序排序。
对于数值类型(如Integer、Double),TreeSet默认按照数值本身的大小进行升序排序。
对于字符串类型,TreeSet默认按照首字符的Unicode编码进行升序排序。
对于自定义类型(如自定义对象),如果对象没有实现Comparable接口或没有提供Comparator对象,则无法直接添加到TreeSet中。

唯一性保证:

TreeSet通过红黑树的特性保证了元素的唯一性。在添加元素时,TreeSet会遍历红黑树,找到元素应该插入的位置。如果在这个位置上已经存在相同的元素(根据排序规则判断),则不会添加新的元素。

性能特点:

TreeSet的插入、删除和查找操作的平均时间复杂度都是O(log n),其中n是集合中元素的数量。这是因为红黑树在插入、删除和查找元素时,能够保持树的平衡,使得树的高度相对较低,从而提高了操作的效率。
与HashSet相比,TreeSet在插入和删除元素时可能需要更多的计算量来维护红黑树的平衡,但在需要保持元素顺序的场景下,TreeSet提供了更好的性能。

遍历方式:

TreeSet提供了多种遍历方式,包括升序遍历(自然顺序或根据提供的Comparator对象)和降序遍历(使用descendingSet()方法获取降序视图)。

继承关系:

TreeSet实现了NavigableSet接口,该接口扩展了SortedSet接口,提供了更多的导航和排序方法。因此,TreeSet不仅具有Set接口的基本功能,还提供了更丰富的排序和遍历功能。

总的来说,TreeSet通过红黑树数据结构实现了元素的排序和唯一性保证,同时提供了高效的插入、删除和查找操作以及丰富的遍历方式。

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

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

相关文章

C#面:解释什么是WCF?目前最新的版本是多少

WCF(Windows Communication Foundation)是微软提供的一种用于构建分布式应用程序的框架。它提供了一种统一的编程模型,使开发人员能够使用多种通信协议(如HTTP、TCP、MSMQ等)在不同的平台上进行通信。 WCF的主要目标是…

线程传参、线程ID

传递临时对象作线程参数 #include<ioatream> #include<thread> using namespace std; void nowork(const int& a) {cout<<huyanluanyu<<endl; } int main() {int a677;thread newdozer(nowork,a);newdozer.detach(); } 向新创建的线程中传递参数…

【人工智能】博弈搜索(极小极大值、α-β剪枝)

1. 极小极大值算法 人工智能中 “博弈” 通常专指博弈论专家们称为有完整信息的、确定性的、轮流行动的、两个游戏者的零和游戏&#xff08;如国际象棋)。术语中&#xff0c;这是指在确定的、完全可观察的环境中两个 Agent必须轮流行动&#xff0c;在游戏结束时效用值总是相等并…

Python 进阶(十九):解析命令行参数(argparse 模块)

大家好&#xff0c;我是水滴~~ 当处理命令行参数时&#xff0c;Python 的 argparse 模块是一个强大而灵活的工具。它提供了一个简单且一致的方式来定义命令行参数、选项和子命令&#xff0c;并帮助你解析和验证用户提供的输入。本教程将详细介绍 argparse 模块的使用方法和常见…

Ansys电力变压器解决方案

电力变压器设计挑战 目前面临的挑战&#xff1a; 1、磁场 • 非线性材料 • 涡流电流 • 磁场随时间的变化 • 瞬态激励源下的磁场变化 • 空间磁场分布 2、电场 • 介电常数的变化 • 电极的尺寸和形状 • 空间电场分布 变压器的两个类别 变压器可以分为两类进行F…

springboot项目中引入Xxl-Job并部署和使用

目录 模块划分 配置调度中心 配置执行器 添加执行器 写一个简单的定时任务 XxlJobHelper xxl-job是分布式任务调度平台&#xff0c;部署为独立的调度服务平台 github地址&#xff1a;xuxueli/xxl-job: A distributed task scheduling framework.&#xff08;分布式任务调度…

视频怎么去水印?这三款工具助你轻松搞定

在视频处理的过程中&#xff0c;水印常常成为我们的一大难题。它不仅影响了视频的美观度&#xff0c;还可能涉及版权问题。那么&#xff0c;如何高效去除视频中的水印呢&#xff1f;接下来&#xff0c;我将为大家推荐三款国内外备受好评的视频去水印工具&#xff1a;水印云、In…

Jmeter性能测试(五)

一、Jmeter参数化常用方式 1、CSV 数据文件设置 2、查询数据库(JDBC Connection Configuration) 二、CSV 数据文件设置 1、准备一个txt文件(不需要写表头&#xff0c;直接写你要用的数据就行了&#xff0c;多个字段用英文逗号隔开) 2、添加一个CSV 数据文件设置(放全局最上…

让《行列视》解放数据力量,提升业务洞察

在当今信息化浪潮下&#xff0c;数据已经成为企业发展的核心驱动力之一。如何更好地管理和利用数据&#xff0c;已成为企业发展过程中亟需解决的问题之一。而报表工具作为数据可视化和分析的利器&#xff0c;正逐渐受到企业的重视和青睐。 一、《行列视》作为报表工具的重要性…

RabbitMQ基础入门

初识MQ 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&#xff0c;但是你却不能跟多个人同…

栈的2道面试题【有效的括号】【用栈实现队列】

栈的面试题&#xff1a; 1.有效的括号 题目&#xff1a; 有效的括号 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合…

560. 和为 K 的子数组 974. 和可被 K 整除的子数组 【前缀和】

题目链接 ​​​​​​​974. 和可被 K 整除的子数组 560. 和为 K 的子数组 今天刷题的时候&#xff0c;刷了这两题&#xff0c;感觉挺有意思的。代码写起来挺简单的&#xff0c;但是思路和其中的细节以及涉及到的知识点确实让我挺意外的。这里写个博客解析一波&#xff0c;也是…

一个月速刷leetcodeHOT100 day02

今天的三道题 移动零 在双指针分组里的简单题 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 输入: nums [0,1,0,3,12] 输出: [1,3,12,0…

Python自动化下载指定公开页面文件

示例代码如下&#xff0c;但你拿到本地之需要做两件事才能运行 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys import time# 设置Se…

计算机组成原理(超详解!!) 第七节 中央处理器(上)

1.CPU的功能和组成 CPU的功能&#xff1a; 指令控制&#xff1a;程序的顺序控制。 操作控制&#xff1a;管理并产生每条指令的操作信号&#xff0c;并把它们送到相应部件&#xff0c;控制这些部件按要求进行动作。 时间控制&#xff1a;对各种操作实施…

MySQL表分区深入指南

MySQL的表分区功能允许将一个表的数据分散存储在多个物理子表中&#xff0c;但在逻辑上仍表现为一个单独的表。这可以帮助提高大型数据库表的查询和维护效率。本文将详细介绍如何在MySQL中实施和管理表分区&#xff0c;包括分区类型、创建分区表的步骤&#xff0c;以及分区表的…

Day_3

1. HttpClient HttpClient是Apache的一个子项目&#xff0c;是高效的、功能丰富的支持HTTP协议的客户端编程工具包 作用&#xff1a;发送HTTP请求&#xff0c; 接受相应数据 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>…

ES集群搭建、身份认证配置

虚机搭建 添加es用户 elasticsearch 默认不允许root用户启动&#xff0c;所以需要创建es用户 useradd elasticsearch passwd elasticsearch解压安装包 #解压es tar -xvzf elasticsearch-7.14.2-linux-x86_64.tar.gz将文件夹赋予es用户权限 #将文件夹赋予es用户权限 sudo c…

controlnet的preprocessor类型

GitHub - huggingface/controlnet_auxContribute to huggingface/controlnet_aux development by creating an account on GitHub.https://github.com/huggingface/controlnet_aux/https://huggingface.co/lllyasviel/sd_control_collection

js中日期Date的使用

日常搬砖过程中,凡事使用到Date总是一知半解,每次都要查阅资料,今天有时间把这里整理一下,希望今天储备的知识,够以后使用就不用查阅资料了哈,现在开始吧 new Date() 使用它可以创建一个日期实例,并返回代表当前时间的字符串 接收参数有5种形式 无参数,新创建的 Date 对象代…