Java中set接口的学习

news/2024/9/21 14:08:02/文章来源:https://www.cnblogs.com/BingBing-8888/p/18423953

Set接口


目录
  • Set接口
    • HashSet
    • TreeSet
    • LinkedHashSet
    • EnumSet
    • CopyOnWriteArraySet

HashSet

Java中的HashSet是集合框架中非常重要的一个类,它实现了Set接口,提供了存储不重复元素的功能。

特点

  1. 无序性:HashSet不保证元素的顺序,即元素的存储顺序与插入顺序无关。遍历HashSet的结果是无序的,即使每次遍历的结果可能相同,但并不代表元素是按照特定的顺序存储的。
  2. 唯一性:HashSet中不允许包含重复的元素。当向HashSet添加元素时,它会使用元素的hashCode()方法来确定元素的存储位置,并使用equals()方法来判断元素的唯一性。如果两个元素的hashCode()相等且equals()返回true,则HashSet将不会存储第二个元素。
  3. 基于哈希表实现:HashSet内部使用哈希表数据结构来存储元素。哈希表通过将元素的键转换为哈希码(即整数)来确定元素的存储位置,这使得HashSet具有快速的插入、删除和查找操作的特性。
  4. 允许空元素:HashSet可以存储null元素,实际上它可以存储最多一个null元素,因为HashSet不允许重复元素。
  5. 非线程安全:HashSet不是线程安全的,如果多个线程同时访问和修改同一个HashSet实例,可能会导致不确定的结果。如果需要在多线程环境中使用HashSet,可以使用Collections.synchronizedSet()方法将其转换为线程安全的集合,或者使用ConcurrentHashMap等线程安全的集合。

底层数据结构

HashSet的底层依赖于HashMap的数据结构,即一个哈希表。这个哈希表是一个数组,数组中的每个元素都是一个链表或红黑树(Java 8以后引入了红黑树优化)。当向HashSet中添加元素时,并不是直接将元素放入数组,而是将元素作为HashMap的key来存储,而对应的value则是一个固定的对象——PRESENT(一个私有的、唯一的Object实例),用于占位,表示这个键存在于HashSet中。

常用方法

HashSet提供了丰富的常用方法来操作集合中的元素,以下是一些主要的方法:

  1. 添加元素

    • add(Object obj):将元素添加到HashSet中,如果已存在则不添加,返回true表示添加成功,false表示元素已存在。
  2. 删除元素

    • remove(Object obj):从HashSet中移除指定的元素,返回true表示移除成功,false表示元素不存在。
  3. 检查元素

    • contains(Object obj):检查HashSet是否包含指定的元素,返回true表示存在,false表示不存在。
  4. 清空集合

    • clear():清空HashSet中所有的元素。
  5. 获取集合大小

    • size():返回HashSet中元素的个数。
  6. 判断集合是否为空

    • isEmpty():判断HashSet是否为空,如果为空则返回true,否则返回false
  7. 遍历集合

    • 可以使用Iterator迭代器或增强的for-each循环来遍历HashSet中的元素。需要注意的是,由于HashSet是无序的,所以遍历的结果也是无序的。

综上所述,HashSet是一个基于哈希表实现的、无序且不包含重复元素的集合类,它提供了丰富的常用方法来操作集合中的元素。在使用时需要注意其无序性和非线程安全性的特点,并根据需要选择合适的集合类来满足不同的需求。

TreeSet

Java中的TreeSet是一个基于红黑树(Red-Black Tree)实现的NavigableSet接口的实现类,它提供了一系列与排序相关的特性。

特点

  1. 有序性:TreeSet中的元素按照升序排列。默认情况下,如果元素实现了Comparable接口,则按照元素的自然顺序进行排序;如果没有实现Comparable接口,则需要在创建TreeSet时提供一个Comparator来指定排序规则。
  2. 唯一性:TreeSet不允许存储重复的元素。当尝试向TreeSet中添加重复元素时,添加操作会失败,并且元素不会被添加到集合中。
  3. 动态数据结构:TreeSet是一个动态的数据结构,它可以根据需要自动地调整其内部容量来存储更多的元素。
  4. 性能:TreeSet的插入、删除和查找操作的时间复杂度通常为O(log N),其中N是TreeSet中元素的数量。这是因为红黑树是一种自平衡的二叉查找树,它能够保持树的平衡性,从而保证这些操作的高效性。
  5. 线程不安全:TreeSet不是线程安全的,如果多个线程同时访问和修改TreeSet,则需要在外部进行同步处理。

底层数据结构

TreeSet的底层数据结构是红黑树(Red-Black Tree)。红黑树是一种自平衡的二叉查找树,它通过特定的规则和旋转操作来保持树的平衡性,从而确保在动态数据结构中维持排序和二分搜索的性能。红黑树的每个节点都包含颜色属性(红色或黑色),并遵循以下规则:

  • 每个节点要么是红色,要么是黑色。
  • 根节点是黑色的。
  • 每个叶节点(NIL或空节点)是黑色的。
  • 如果一个节点是红色的,则它的两个子节点都是黑色的。
  • 对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

这些规则保证了红黑树的平衡性,并使得在插入、删除和查找等操作中的时间复杂度能够保持在O(log N)。

常用方法

TreeSet提供了一系列与集合操作相关的方法,包括添加、删除、查找、遍历等。以下是一些常用的方法:

  • add(Object o):将指定元素添加到TreeSet中。如果该元素已经存在,则不添加。
  • remove(Object o):从TreeSet中移除指定元素。
  • contains(Object o):检查TreeSet中是否包含指定元素。
  • size():返回TreeSet中元素的数量。
  • first():返回TreeSet中的第一个元素(即最小的元素)。
  • last():返回TreeSet中的最后一个元素(即最大的元素)。
  • iterator():返回一个迭代器,用于按照元素的自然顺序或Comparator指定的顺序遍历TreeSet。
  • descendingIterator():返回一个逆序迭代器,用于按照与迭代器相反的顺序遍历TreeSet。
  • headSet(Object toElement):返回TreeSet中所有小于指定元素的子集合,该子集合也是一个TreeSet。
  • tailSet(Object fromElement):返回TreeSet中所有大于或等于指定元素的子集合,该子集合也是一个TreeSet。
  • subSet(Object fromElement, Object toElement):返回TreeSet中从指定起始元素(包括)到指定结束元素(不包括)之间的子集合,该子集合也是一个TreeSet。

需要注意的是,TreeSet中的元素必须是可比较的,因此如果要将自定义对象存储在TreeSet中,需要实现Comparable接口或使用Comparator比较器来指定排序方式。

LinkedHashSet

Java中的LinkedHashSet是HashSet的一个子类,它继承了HashSet的所有特性,并在此基础上增加了保持元素插入顺序的能力。

特点

  1. 有序性:LinkedHashSet通过内部维护一个双向链表来记录元素的插入顺序,因此它遍历元素时是按照元素的插入顺序进行的。这与HashSet的无序性形成对比。
  2. 唯一性:与HashSet一样,LinkedHashSet也不允许集合中存在重复元素。如果尝试添加已经存在的元素,则添加操作会被忽略。
  3. 基于哈希表和链表实现:LinkedHashSet的底层数据结构是由哈希表和链表组成的。哈希表用于保证元素的唯一性,而链表则用于维护元素的插入顺序。
  4. 性能:由于需要维护元素的插入顺序,LinkedHashSet的性能相对于HashSet来说会稍微低一些。特别是插入和删除操作,因为它们需要同时更新哈希表和链表。
  5. 线程不安全:和HashSet一样,LinkedHashSet也不是线程安全的集合类。如果多个线程同时修改集合中的元素,可能会导致数据不一致的问题。

底层数据结构

LinkedHashSet的底层数据结构是由哈希表和双向链表组成的。哈希表用于存储元素及其对应的哈希码,以支持快速的查找、插入和删除操作。而双向链表则用于记录元素的插入顺序,以支持按照插入顺序遍历元素。这种组合结构使得LinkedHashSet既能够保持元素的唯一性,又能够保持元素的插入顺序。

常用方法

LinkedHashSet提供了丰富的常用方法来操作集合中的元素,以下是一些主要的方法:

  • 添加元素add(E e),向集合中添加元素。如果元素已经存在,则不会进行添加操作。
  • 删除元素remove(Object o),从集合中删除指定的元素。如果元素不存在,则不会进行删除操作。
  • 判断元素是否存在contains(Object o),判断集合中是否包含指定的元素。
  • 获取集合大小size(),返回集合中元素的数量。
  • 判断集合是否为空isEmpty(),判断集合是否为空。
  • 清空集合clear(),清空集合中的所有元素。
  • 遍历集合:可以使用增强for循环或迭代器(Iterator<E>)来遍历集合中的元素。遍历结果将按照元素的插入顺序进行。
  • 克隆集合clone(),返回集合的一个浅拷贝。
  • 将集合转换为数组toArray(),将集合转换为一个数组。
  • 比较集合equals(Object o),比较两个集合是否相等。如果两个集合包含的元素相同且元素的顺序也相同,则这两个集合相等。
  • 获取集合的哈希码hashCode(),返回集合的哈希码。
  • 将集合转换为字符串toString(),返回集合的字符串表示形式。

总的来说,LinkedHashSet是一个有序且不重复的集合类,它适合在需要保持元素插入顺序的场景下使用。通过合理运用其提供的常用方法,可以方便地对集合进行操作和管理。

EnumSet

Java中的EnumSet是专门为枚举类型设计的一个高效集合实现,它继承自AbstractSet<E>类并实现了Set<E>接口。

特点

  1. 高效性:EnumSet在内部使用位向量(bit vector)来存储枚举常量,因此在时间和空间上都非常高效。特别是当枚举类型的常量数目较小时,EnumSet的性能优势更加明显。
  2. 类型安全:EnumSet只能包含单个枚举类型的值,这使得它比其他集合类更为类型安全。
  3. 有序性:EnumSet中的元素会按照枚举类型中声明的顺序进行排序,这保证了集合元素的有序性。
  4. 不允许null元素:EnumSet不允许插入null元素,这是由枚举类型的特性决定的。
  5. 便捷性:EnumSet提供了一系列静态工厂方法来创建实例,如allOfnoneOfofrange等,使得使用起来非常方便。

底层数据结构

EnumSet的底层数据结构是位向量(bit vector)。位向量是一种数据结构,它使用单个位的集合来表示元素的存在与否。在EnumSet中,每个枚举常量都对应位向量中的一个位,如果该位被设置为1,则表示对应的枚举常量存在于集合中;如果该位被设置为0,则表示对应的枚举常量不存在于集合中。这种表示方法使得EnumSet在存储和操作枚举常量时非常高效。

常用方法

EnumSet提供了一系列与Set接口一致的方法,如addremovecontainssize等,同时还提供了一些特有的方法,如allOfnoneOfofrange等。以下是常用方法的简要介绍:

  • add(E e):向EnumSet中添加一个元素。如果该元素已经存在,则添加操作将被忽略。
  • remove(Object o):从EnumSet中移除一个元素。如果该元素不存在,则移除操作将被忽略。
  • contains(Object o):检查EnumSet中是否包含指定的元素。
  • size():返回EnumSet中元素的数量。
  • allOf(Class elementType):创建一个包含指定枚举类型的所有元素的EnumSet。
  • noneOf(Class elementType):创建一个空的EnumSet,其元素类型为指定的枚举类型。
  • of(E e, E... elements):创建一个包含指定元素的EnumSet。这是一个可变参数方法,可以接受一个或多个枚举常量作为参数。
  • range(E from, E to):创建一个包含从fromto(包括两者)之间所有元素的EnumSet。需要注意的是,fromto必须是同一枚举类型中的有效常量,并且from的值必须小于或等于to的值。

此外,EnumSet还支持一些集合操作,如unionintersectioncomplement等,这些操作可以方便地对两个或更多个EnumSet实例进行位运算与集合运算。

综上所述,EnumSet是Java中专门为枚举类型设计的一个高效集合实现,它通过位向量来存储枚举常量,具有高效性、类型安全、有序性和便捷性等特点。在实际开发中,当需要处理一组固定的常量,并且这些常量属于同一个枚举类型时,使用EnumSet是一个很好的选择。

CopyOnWriteArraySet

Java中的CopyOnWriteArraySet是一个线程安全的Set集合,它基于CopyOnWriteArrayList实现,适用于读多写少的并发场景。

特点

  1. 线程安全CopyOnWriteArraySet通过写时复制(Copy-On-Write)的策略来保证线程安全。每次修改集合时(如添加、删除元素),都会复制底层数组,并在新数组上进行修改,然后将引用指向新数组,从而避免并发冲突。
  2. 读操作高效:由于读操作不需要加锁,且始终读取的是一致的数组快照,因此读操作非常高效。
  3. 写操作开销大:写操作(如添加、删除元素)需要复制整个底层数组,因此开销较大。特别是在数据量较大的情况下,写操作可能会成为性能瓶颈。
  4. 迭代器弱一致性:迭代器不会抛出ConcurrentModificationException,但也不会反映迭代器创建之后对集合的修改。迭代器的数据来源于迭代时的快照数据。
  5. 适用场景:适用于读多写少且数据量不是特别大的并发场景,如缓存等。

底层数据结构

CopyOnWriteArraySet的底层数据结构是基于CopyOnWriteArrayList实现的。CopyOnWriteArrayList内部使用动态数组(Object[]数组)来存储元素,并通过写时复制的策略来保证线程安全。因此,CopyOnWriteArraySet也间接地使用了动态数组作为其底层数据结构。

常用方法

CopyOnWriteArraySet继承自AbstractCollection<E>并实现了Set<E>接口,因此它提供了Set接口的所有方法。以下是一些常用的方法:

  • add(E e):向集合中添加元素。如果集合中不存在该元素,则添加成功;否则,添加失败。
  • remove(Object o):从集合中移除指定的元素。如果集合中存在该元素,则移除成功;否则,移除失败。
  • contains(Object o):检查集合中是否包含指定的元素。
  • size():返回集合中元素的数量。
  • isEmpty():检查集合是否为空。
  • clear():清空集合中的所有元素。
  • iterator():返回集合的迭代器,用于遍历集合中的元素。

需要注意的是,由于CopyOnWriteArraySet的写操作开销较大,因此在写操作频繁的并发场景下,其性能可能会受到影响。此外,由于其迭代器是弱一致性的,因此在迭代器上进行的修改操作可能不会立即反映在集合中。

总的来说,CopyOnWriteArraySet是一个适用于特定场景的线程安全集合,其特点、底层数据结构以及常用方法都体现了其设计理念和适用场景。在实际开发中,应根据具体需求选择合适的集合类来实现功能。

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

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

相关文章

人员离岗自动识别系统

人员离岗自动识别系统依据深度学习机器视觉技术,人员离岗自动识别系统能够自动识别岗位上是否人员存在。一旦发现人员在作业时间不在位置上,人员离岗自动识别系统会立即抓拍报警,并把报警记录同步到后台,通过现场语音摄像机给出语音提示,让人员及时返回岗位。通过现场语音…

怎么查看数据库的用户名和密码

查看数据库的用户名和密码取决于你使用的数据库管理系统(DBMS)以及你所拥有的权限。以下是几种常见数据库系统中查看用户名和密码的方法: MySQL 对于MySQL数据库,如果你有足够的权限,可以通过查询mysql.user表来查看用户列表及其相关信息。密码是以哈希形式存储的,不能直…

人员抽烟行为识别检测系统

人员抽烟行为识别检测系统依据智能视频分析,对监控画面开展724h无间断分析。大大提升了视频资源的使用率,减少了人力成本。人员抽烟行为识别检测系统识别管控区域人员的抽烟状况。当发现异常状况时,以迅速的方式进行预警提醒。人员抽烟行为识别检测系统优化算法识别率高,识…

数据库连接错误:您在wp-config.php文件中提供的数据库用户名和密码可能不正确,或者无法连接到localhost上的数据库服务器

为了解决“数据库连接错误”的问题,可以按照以下步骤进行操作:备份现有配置:在修改任何文件之前,请确保备份现有的wp-config.php文件,以防修改出错时能够恢复。重命名配置文件:将根目录下的wp-config-sample.php文件重命名为wp-config.php。这通常可以通过FTP客户端或通过…

网站后台用户名和密码不对怎么办

如果你遇到网站后台用户名和密码不正确的问题,可以尝试以下步骤来解决:检查输入:确认没有多余的空格。 注意大小写是否正确。 确认是否使用了正确的用户名(有些系统使用邮箱地址作为用户名)。重置密码:如果网站提供了“忘记密码”功能,请尝试使用此功能来重置密码。 检查…

智慧工地抽烟识别检测系统

智慧工地抽烟识别检测系统根据计算机深度学习+边缘视觉分析技术,智慧工地抽烟识别检测系统自动分析识别监控视频画面图片数据,无需人工控制;系统对监控画面中人员的吸烟行为进行识别,及时发现监管画面中人员的违规行为,立即抓拍存档并同步违规信息到后台,有效帮助后台人员…

网站数据库用户名和密码错误:如何解决?

当遇到“数据库用户名和密码错误”的问题时,可以按照以下步骤来解决: 1. 核对凭证检查输入:确保输入的数据库用户名和密码完全正确,包括大小写和空格。 默认凭证:如果是默认的用户名(如root),确保默认密码正确。有些情况下,默认密码为空或为特定值(如root)。2. 重置…

网站无法访问,提示数据库连接失败,用户名和密码不正确?

当网站提示数据库连接失败,并指出用户名和密码不正确时,可以采取以下步骤来诊断并解决这个问题:确认数据库凭证检查应用程序配置文件中用于连接数据库的用户名和密码是否正确。常见的配置文件有.env、database.ini、database.properties等,具体取决于使用的框架或语言。 如…

解决数据库登录失败问题,教你如何处理用户名错误

当遇到数据库登录失败,并且确定问题是由于用户名或密码错误导致时,可以按照以下步骤来解决问题:核实凭证确认输入的用户名和密码是否正确无误。 检查是否有大小写错误,因为大多数数据库系统对于用户名和密码都是区分大小写的。 确保没有在用户名或密码前后添加了空格或其他…

数据库用户名和密码错误:如何解决?

当你遇到数据库用户名和密码错误的问题时,可以按照以下步骤来解决这个问题:确认凭证再次检查输入的数据库用户名和密码是否正确。有时候简单的拼写错误或大小写错误都会导致连接失败。 如果你是从某个地方复制粘贴的用户名和密码,请确保没有多余的空格或其他字符。默认凭证如…

帝国cms网站更换域名后图片地址更换的方法

当帝国CMS更换域名后,图片地址也需要相应地更新,以保证图片可以正常显示。以下是几种更换帝国CMS中图片地址的方法: 1. 更新数据库中的图片路径 如果图片路径是以绝对路径的形式存储在数据库中,那么可以通过更新数据库的方式来修改图片地址。 步骤:登录数据库管理工具:使…

帝国cms备份和恢复 帝国cms恢复数据

帝国CMS的备份和恢复功能可以帮助你在数据丢失或需要迁移网站时快速恢复数据。以下是详细的步骤,介绍如何进行帝国CMS的备份和恢复操作: 帝国CMS备份数据 通过帝国CMS后台备份登录帝国CMS后台:使用管理员账号登录帝国CMS后台。 进入备份与恢复模块:在后台管理界面中找到“系…