1. Set接口

  • Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。
  • Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

2. HashSet

HashSet有以下特点:

  • 不能保证元素的排列顺序,顺序有可能发生变化
  • 不是同步的,集合元素可以是null

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值来决定该对象在HashSet中存储位置。简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相等。

注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对象通过equals方法比较返回true时,其hashCode也应该相同。

3. LinkedHashSet

  • LinkedHashSet与HashSet的不同之处在于,LinkedHashSet维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。
  • LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置。

4. TreeSet

  • TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。
  • TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
  • TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0

自然排序根据排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。
Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。
obj1.compareTo(obj2)方法如果返回0,则说明被比较的两个对象相等,如果返回一个正数,则表明obj1大于obj2,如果是负数,则表明obj1小于obj2。
如果我们将两个对象的equals方法总是返回true,则这两个对象的compareTo方法返回应该返回0。如果要定制排序,应该使用Comparator接口,实现int compare(To1,To2)方法

5. 性能分析

  • HashSet用的哈希表,开一个大数组,用哈希值映射到下标上,会有冲突,只有装填因子小的时候性能才好;
  • HashSet要留额外空间,占内存大,数据频繁插入的时候可能会不断触发Array Copy,但是读写性能一般很快;
  • TreeSet底层用红黑树实现,读写性能差一些,但不存在Array Copy问题,并且不占用额外的不存储数据的空间;
  • 一般来说空间换时间或者时间换空间。HashSet的查找代价为O(1),TreeSet为O(logn);
  • TreeSet的设计本身不是为了空间时间的问题,而是为了有序。因此它的插入及查找操作的代价都大于HashSet;
  • HashSet性能要好于TreeSet(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法维护集合元素的次序。

  • LinkedHashSet对于普通的插入,删除操作比HashSet要略微慢一点,这是由维护链表所带来的额外开销造成的,但由于有了链表,遍历LinkedHashSet会更快;
  • EnumSet是所有Set实现类中性能最好的,但它只能保存同一个枚举类的枚举值作为集合元素;

6. 线程安全

注意:Set的三个实现类HashSet、TreeSet和EnumSet都是线程不安全的。
如果有多个线程同事访问一个Set集合,并且有超过一个线程修改了该Set集合,则必须手动保证该Set集合的同步。

  • 解决:通常通过Collections工具类的synchronizedSortedSet方法来“包装”该Set集合。
  • 注意:此操作最好在创建时进行,以防止对Set集合的意外非同步访问。
  • 示例:SortedSet set = Collections.synchronizedSortedSet(new TreeSet());

Collections 工具类其他同步方法:

  • synchronizedCollection(Collection<T> c)
    这个方法返回一个同步的(线程安全的)集合的指定集合的支持。
  • synchronizedList(List<T>list)
    这个方法返回由指定列表支持的同步(线程安全的)列表。
  • synchronizedMap(Map<K,V> m)
    这个方法返回一个同步的(线程安全)由指定映射支持。
  • synchronizedSet(Set<T> s)
    这个方法返回一个同步的(线程安全的)集由指定set支持。
  • synchronizedSortedMap(SortedMap<K,V> m)
    这个方法返回一个同步的(线程安全的)有序映射所指定的有序映射支持
  • synchronizedSortedSet(SortedSet<T> s)
    这个方法返回一个同步的(线程安全的)有序set由指定的有序set支持。
  • synchronizedNavigableMap(NavigableMap<K,V> m)(JDK1.8)
  • synchronizedNavigableSet(NavigableSet<T> s)(JDK1.8)

7. 快速失败

什么是集合迭代器快速失败行为?以ArrayList为例,在多线程并发情况下,如果有一个线程在修改ArrayList集合的结构(插入、移除...),而另一个线程正在用迭代器遍历读取集合中的元素,此时将抛出ConcurrentModificationException异常立即停止迭代遍历操作,而不需要等到遍历结束后再检查有没有出现问题;

  • Collection类返回一个Iterator之后,其实会创建一个指向原来对象的单链索引表,当原来的对象数量发生变化的时候,这个单链索引表的内容不会同步改变,所以当索引指针往后移动的时候,找不到要找的对象,就会按照fail-fast原则(快速失败原则),Iterator马上跑出java.util.ConcurrentModificationException异常。换一个说法,也就是,在Iterator工作的时候,是不允许被迭代的对象改变的。
  • 避免抛出这个异常的方法是:不使用Collection自身的remove()方法,而使用Iterator本身的方法remove()来删除对象,因为这样子可以删掉原对象,同时当前迭代对象的索引也得到同步。

HashSet,TreeSet和LinkedHashSet的区别的更多相关文章

  1. HashSet,TreeSet和LinkedHashSet的区别

    Set接口Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就是说,只要两个对象用eq ...

  2. Set下面HashSet,TreeSet和LinkedHashSet的区别

    Set接口Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就是说,只要两个对象用eq ...

  3. 【java提高】---HashSet 与TreeSet和LinkedHashSet的区别

    HashSet 与TreeSet和LinkedHashSet的区别 今天项目开发,需要通过两个条件去查询数据库数据,同时只要满足一个条件就可以取出这个对象.所以通过取出的数据肯定会有重复,所以要去掉重 ...

  4. HashSet 与TreeSet和LinkedHashSet的区别

    Set接口      Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.      Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就 ...

  5. HashSet,TreeSet和LinkedHashSet

    Set接口 Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false. Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就是说,只要两个对象用 ...

  6. Leetcode: LFU Cache && Summary of various Sets: HashSet, TreeSet, LinkedHashSet

    Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...

  7. Java集合详解7:HashSet,TreeSet与LinkedHashSet

    今天我们来探索一下HashSet,TreeSet与LinkedHashSet的基本原理与源码实现,由于这三个set都是基于之前文章的三个map进行实现的,所以推荐大家先看一下前面有关map的文章,结合 ...

  8. Set集合[HashSet,TreeSet,LinkedHashSet],Map集合[HashMap,HashTable,TreeMap]

    ------------ Set ------------------- 有序: 根据添加元素顺序判定, 如果输出的结果和添加元素顺序是一样 无序: 根据添加元素顺序判定,如果输出的结果和添加元素的顺 ...

  9. Java集合详解7:一文搞清楚HashSet,TreeSet与LinkedHashSet的异同

    <Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...

随机推荐

  1. 表单中method="post"什么意思?

    表示表单中的数据以"post"方法传递.Form提供了两种数据传输的方式——get和post.虽然它们都是数据的提交方式,但是在实际传输时确有很大的不同,并且可能会对数据产生严重的 ...

  2. Eclipse 悬浮提示

    Eclipse 悬浮提示 使用悬浮提示 java 编辑器中包含了不同类型的悬浮提示,悬浮提示提供了鼠标指针指向元素的额外信息.所有java编辑器中相关的悬浮提示可以通过 preference(首选项) ...

  3. 一个简单的servlet容器

    [0]README 0.1)本文部分文字转自 “深入剖析Tomcat”,旨在学习  一个简单的servlet容器  的基础知识: 0.2)for complete source code, pleas ...

  4. 嵌入式开发之赛灵思 xilinx Zynq芯片简介---Zynq-7000 EPP (XC7Z010 and XC7Z020)

    (1)企业简介 作为DSP 和视频应用领域的头号 FPGA 供应商,赛灵思致力于通过其目标设计平台提供业内领先的 DSP 开发工具.方法.IP 和技术支持.赛灵思面向 DSP 的目标设计平台将这些元素 ...

  5. openstack组件通讯端口定义

    openstack 组件通讯是通过ZeroMQ+ceilometer发送组件调用信息,具体是通过TCP通讯,发送数据和接收数据是用同一个端口(在配置文件指定),下面通过代码稍作解析: IceHouse ...

  6. 【BZOJ2762】[JLOI2011]不等式组 树状数组

    [BZOJ2762][JLOI2011]不等式组 Description 旺汪与旺喵最近在做一些不等式的练习.这些不等式都是形如ax+b>c 的一元不等式.当然,解这些不等式对旺汪来说太简单了, ...

  7. C# MD5加密与校验 引用

    using System; using System.Security.Cryptography; using System.Text; class Example { // Hash an inpu ...

  8. 六百字读懂 Git(转)

    add by zhj:还是原文 六百字读懂 Git 看着更舒服一些,显示更好 原文:六百字读懂 Git 英文原文:Git in 600 words 译注:来自 Hacker School 的 Mary ...

  9. 前端基础 & Bootstrap框架

    Bootstrap介绍 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应用程序而设计的一套前端工具包. 它支持响应式布局,并且 ...

  10. Android系统移植与调试之------->如何修改Android手机显示的4G信号强度的格子数

    在修改显示的信号强度之前,先了解一下什么是dB,什么是dBm? 1.dB dB是一个表征相对值的值,纯粹的比值,只表示两个量的相对大小关系,没有单位,当考虑甲的功率相比于乙功率大或小多少个dB时, 按 ...