• HashSet和LinkedHashSet解析


    一、简介

    1、Set概念

    Set可以理解为集合,非常类似数据概念中的集合,集合三大特征:1、确定性;2、互异性;3、无序性,因此Set实现类也有类似的特征。

    2、HashSet

    HashSet继承自AbstractSet,实现了Set接口,但是其源码非常少,也非常简单。内部使用HashMap来存储数据,数据存储在HashMap的key中,value都是同一个默认值:

    二、HashSet几个重要的方法

    1、add(E e)

    HashSet的确定性,也可以理解为唯一性,是通过HashMap的put方法来保证的,往HashMap中put数据时,如果key是一样的,只会替换key对应的value,不会新插入一条数据。所以往HashSet中add相同的元素没有什么用,这里的相同是通过equals方法保证的,具体的在HashMap中细说。

    2、remove(Object o)

    简单粗暴,从HashMap中移除一条数据。

    3、contains(Object o)

    4、iterator()

    5、其他

    其他的方法诸如:size()、isEmpty()、contains()、clear()等都完全委托给了HashMap。需要注意的是:HashSet没有提供set、get等方法。

     源码如下:

     View Code

    三、LinkedHashSet

    1、LinekdHashSet简介

    LinkedHashSet继承自HashSet,源码更少、更简单,唯一的区别是LinkedHashSet内部使用的是LinkHashMap。这样做的意义或者好处就是LinkedHashSet中的元素顺序是可以保证的,也就是说遍历序和插入序是一致的。

    2、Demo使用

    打印日志如上,HashSet和HashMap都不保证顺序,Link**能保证顺序。

    源码如下:

     View Code

    3、debug中奇异现象

    如上,我们明明添加了6个元素,但是table中只有5个,怎么回事呢?初步猜测应该是“c”元素和其中某一个元素位于同一个bucket,验证如下:

    我们发现,“java”竟然和“c”位于同一个bucket,他俩在同一个链表中。唯一的疑惑是:“c”是后加入的元素,按理说应该在链表的表头才对啊,这个问题还需要探究。

    同时这里也介绍了一种能debug到HashMap内部数据结构的方法,但是需要注意2个问题:

    1、需要在AS中设置一下,否则debug看到的信息不是这样的,如下图:

    2、直接使用table[3].next是不行的, 需要像图上那样,些完整的包名才行。

    4、继续debug

    如上所示,设置HashSet之后,同样能看到如下信息:

    看看LinkedHashMap,如下图,LinkedHashMap中多了head和tail,这是指向表头、表尾的指针,head指向“java”,tail指向“c”,这和我们的插入序保持一致,但是实际存储和之前是一样的。

     LinkedHashSet如下图:

  • 相关阅读:
    [Windows] 输入字符间距变宽
    [Android] 安卓手机不用root删除自带app
    [Linux] 内核通知链 notifier
    [RK3399] ES8316+NS4150 播放视频只有背景音,播放歌曲有的有声音,有的无声音
    [Linux] RTC 读写指令及测试程序
    [Linux] scp指令用法
    [Ubuntu] sudo apt-get update指令执行失败
    [RK3399] 修改移动网络默认为4G
    [RK3288] 外接USB设备出现丢数
    laravel 模拟数据批量添加
  • 原文地址:https://www.cnblogs.com/maohuidong/p/10061627.html
Copyright © 2020-2023  润新知