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. Python使用MySQL数据库的

    然而,2016年开始,我从Python2切换到了Python3,Python2已经基本不再使用,MySQLdb驱动从2014年1月停止了维护.所以,打算重新再来写这篇博客. Python2 ---&g ...

  2. mysql UNION all 实现不对称数据统计

    当统计多条的三个参数在不同时间段的数据的sum,又只能写在同一个sql上时,可以考虑union all三次查询, select * from ( select kk.a_time as dates,k ...

  3. 【BZOJ2870】最长道路tree 点分治+树状数组

    [BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来 ...

  4. 《从零开始学Swift》学习笔记(Day 45)——重写方法

    原创文章,欢迎转载.转载请注明:关东升的博客 重写实例方法 在子类中重写从父类继承来的实例方法和静态方法.先介绍实例方法的重写. 下面看一个示例: class Person { var name: S ...

  5. Java+selenium自动化测试基础

    Java+selenium maven配置 maven的配置,但还需要建立maven的本地库,修改apach-maven的setting.xml http://www.cnblogs.com/haoa ...

  6. MVC5学习系列

    前言 嗷~小弟我又出现了~咳咳..嚎过头了, 先说一说为什么写这个吧,~首先肯定是我自己需要学(废话 - -,)//,之前也写过MVC4的项目,嗯..但是仅限于使用并没有很深入的每个模块去了解, 这段 ...

  7. C语言练习题

    C语言练习题 1. 以下选项中,合法的一组C语言数值常量是(     ) A)028  .5e-3  .0xf B)12.  OXa23   4.5e0 C).177   4e1.5  Oabc D) ...

  8. 巨蟒django之CRM5 学习记录&&课程记录&&班级管理&&私户的数量上限

    1.公户变私户(事务+行级锁) 2.私户的数量上限 3.班级的管理 4.课程记录管理 5.学习记录的初始化 6.展示和编辑学习记录

  9. spring中实现自己的初始化逻辑

    实现这两个listener都可以进行自己的初始化逻辑. InitializingBean.afterPropertiesSet 这个优先调用 ApplicationListener.onApplica ...

  10. 浅析TCP/IP

    TCP/IP概述 TCP/IP起源于1969年美国国防部(DOD:The United States Department Of Defense)高级研究项目管理局(APRA:AdvancedRese ...