当前位置:首页 > 科技  > 软件

Java的Set集合,你真的会用吗?HashSet/TreeSet/LinkedHashSet

来源: 责编: 时间:2023-12-01 17:13:52 369观看
导读引言当我们需要对元素去重的时候,会使用Set集合,可选的Set集合有三个,分别是HashSet、LinkedHashSet、TreeSet,这三个常用的Set集合有什么区别呢?底层实现原理是什么样?这篇文章一起来深度剖析。共同点这三个类都实现了Set

引言

当我们需要对元素去重的时候,会使用Set集合,可选的Set集合有三个,分别是HashSet、LinkedHashSet、TreeSet,这三个常用的Set集合有什么区别呢?底层实现原理是什么样?这篇文章一起来深度剖析。OYC28资讯网——每日最新资讯28at.com

共同点这三个类都实现了Set接口,所以使用方式都是一样的,使用add()方法添加元素,使用remove()删除元素,使用contains()方法判断元素是否存在,使用iterator()方法迭代遍历元素,这三个类都可以去除重复元素。OYC28资讯网——每日最新资讯28at.com

特性OYC28资讯网——每日最新资讯28at.com

  1. HashSet是最基础的Set集合,可以去除重复元素,元素存储是无序的。
  2. LinkedHashSet在HashSet功能基础上,增加了按照元素插入顺序或者访问顺序的迭代方式。
  3. TreeSet在HashSet功能基础上,可以保证按照元素大小顺序排列。

底层实现OYC28资讯网——每日最新资讯28at.com

  1. HashSet是基于HashMap实现的,使用组合的方式,并非继承。
  2. LinkedHashSet继承自HashSet,而内部则是采用组合LinkedHashMap的方式实现的。[流汗] 就是这么乱,一会儿看一下源码就明白了。
  3. TreeSet是基于TreeMap实现的,采用组合的方式,跟上面两个Set集合没关系。

图片图片OYC28资讯网——每日最新资讯28at.com

下面详细看一下这三个Set集合源码的底层实现:OYC28资讯网——每日最新资讯28at.com

HashSet源码实现

类属性

public class HashSet<E>        extends AbstractSet<E>        implements Set<E>, Cloneable, java.io.Serializable {    /**     * 使用HashMap存储数据     */    private transient HashMap<E, Object> map;    /**     * value的默认值     */    private static final Object PRESENT = new Object();}

可以看出HashSet实现了Set接口,内部采用HashMap存储元素,利用了HashMap的key不能重复的特性,实现元素去重。而value使用默认值,是一个空对象,没有任何作用,纯粹占坑。OYC28资讯网——每日最新资讯28at.com

初始化

HashSet常用的构造方法有两个,有参构造方法,可以指定初始容量和负载系数。OYC28资讯网——每日最新资讯28at.com

/** * 无参构造方法 */HashSet<Integer> hashSet1 = new HashSet<>();/** * 有参构造方法,指定初始容量和负载系数 */HashSet<Integer> hashSet = new HashSet<>(16, 0.75f);

再看一下构造方式对应的源码实现:OYC28资讯网——每日最新资讯28at.com

/** * 无参构造方法 */public HashSet() {    map = new HashMap<>();}/** * 有参构造方法,指定初始容量和负载系数 */public HashSet(int initialCapacity, float loadFactor) {    map = new HashMap<>(initialCapacity, loadFactor);}

HashSet的构造方式源码也很简单,都是利用的HashMap的构造方法实现。OYC28资讯网——每日最新资讯28at.com

常用方法源码

再看一下HashSet常用方法源码实现:OYC28资讯网——每日最新资讯28at.com

/** * 添加元素 */public boolean add(E e) {    return map.put(e, PRESENT) == null;}/** * 删除元素 */public boolean remove(Object o) {    return map.remove(o) == PRESENT;}/** * 判断是否包含元素 */public boolean contains(Object o) {    return map.containsKey(o);}/** * 迭代器 */public Iterator<E> iterator() {    return map.keySet().iterator();}

HashSet方法源码也很简单,都是利用HashMap的方法实现逻辑。利用HashMap的key不能重复的特性,value使用默认值,contains()方法和iterator()方法也都是针对key进行操作。OYC28资讯网——每日最新资讯28at.com

LinkedHashSet源码实现

类属性

LinkedHashSet继承自HashSet,没有任何私有的属性。OYC28资讯网——每日最新资讯28at.com

public class LinkedHashSet<E>        extends HashSet<E>        implements Set<E>, Cloneable, java.io.Serializable {}

初始化

LinkedHashSet常用的构造方法有三个,有参构造方法,可以指定初始容量和负载系数。OYC28资讯网——每日最新资讯28at.com

/** * 无参构造方法 */Set<Integer> linkedHashSet1 = new LinkedHashSet<>();/** * 有参构造方法,指定初始容量 */Set<Integer> linkedHashSet2 = new LinkedHashSet<>(16);/** * 有参构造方法,指定初始容量和负载系数 */Set<Integer> linkedHashSet3 = new LinkedHashSet<>(16, 0.75f);

再看一下构造方法的源码实现:OYC28资讯网——每日最新资讯28at.com

/** * 无参构造方法 */public LinkedHashSet() {    super(16, .75f, true);}/** * 有参构造方法,指定初始容量 */public LinkedHashSet() {    super(16, .75f, true);}/** * 有参构造方法,指定初始容量和负载系数 */public LinkedHashSet(int initialCapacity, float loadFactor) {    super(initialCapacity, loadFactor, true);}

LinkedHashSet的构造方法使用的是父类HashSet的构造方法,而HashSet的构造方法使用的是LinkedHashMap的构造方法,设计的就是这么乱!OYC28资讯网——每日最新资讯28at.com

public class HashSet<E>        extends AbstractSet<E>        implements Set<E>, Cloneable, java.io.Serializable {    /**     * HashSet的构造方法,底层使用的是LinkedHashMap,专门给LinkedHashSet使用     *     * @param initialCapacity 初始容量     * @param loadFactor      负载系数     * @param dummy           这个字段没啥用     */    HashSet(int initialCapacity, float loadFactor, boolean dummy) {        map = new LinkedHashMap<>(initialCapacity, loadFactor);    }}

LinkedHashSet的其他方法也是使直接用的父类HashSet的方法,就不用看了。OYC28资讯网——每日最新资讯28at.com

LinkedHashSet额外实现了按照元素的插入顺序或者访问顺序进行迭代的功能,是使用LinkedHashMap的实现,不了解LinkedHashMap的,可以看一下上篇文章对LinkedHashMap的源码解析。OYC28资讯网——每日最新资讯28at.com

TreeSet源码实现

类属性

public class TreeSet<E> extends AbstractSet<E>        implements NavigableSet<E>, Cloneable, java.io.Serializable {    /**     * 用来存储数据     */    private transient NavigableMap<E, Object> m;    /**     * value的默认值     */    private static final Object PRESENT = new Object();}

TreeSet内部使用NavigableMap存储数据,而NavigableMap是TreeMap的父类,后面在初始化NavigableMap的时候,会用TreeMap进行替换。而value使用默认空对象,与HashSet类似。OYC28资讯网——每日最新资讯28at.com

初始化

TreeSet有两个构造方法,有参构造方法,可以指定排序方式,默认是升序。OYC28资讯网——每日最新资讯28at.com

/** * 无参构造方法 */TreeSet<Integer> treeSet1 = new TreeSet<>();/** * 有参构造方法,传入排序方式,默认升序,这里传入倒序 */TreeSet<Integer> treeSet2 = new TreeSet<>(Collections.reverseOrder());

再看一下构造方法的源码实现:OYC28资讯网——每日最新资讯28at.com

TreeSet(NavigableMap<E,Object> m) {    this.m = m;}/** * 无参构造方法 */public TreeSet() {    this(new TreeMap<E, Object>());}/** * 有参构造方法,传入排序方式,默认升序,这里传入倒序 */public TreeSet(Comparator<? super E> comparator) {    this(new TreeMap<>(comparator));}

TreeSet的构造方法内部是直接使用的TreeMap的构造方法,是基于TreeMap实现的。OYC28资讯网——每日最新资讯28at.com

常用方法源码

/** * 添加元素 */public boolean add(E e) {    return m.put(e, PRESENT) == null;}/** * 删除元素 */public boolean remove(Object o) {    return m.remove(o) == PRESENT;}/** * 判断是否包含元素 */public boolean contains(Object o) {    return m.containsKey(o);}/** * 迭代器 */public Iterator<E> iterator() {    return m.navigableKeySet().iterator();}

TreeSet常用方法的底层实现都是使用的TreeMap的方法逻辑,就是这么偷懒。OYC28资讯网——每日最新资讯28at.com

TreeSet可以按元素大小顺序排列的功能,也是使用TreeMap实现的,感兴趣的可以看一下上篇文章讲的TreeMap源码。由于TreeSet可以元素大小排列,所以跟其他Set集合相比,增加了一些按照元素大小范围查询的方法。OYC28资讯网——每日最新资讯28at.com

其他方法列表:OYC28资讯网——每日最新资讯28at.com

作用
OYC28资讯网——每日最新资讯28at.com

方法签名
OYC28资讯网——每日最新资讯28at.com

获取第一个元素
OYC28资讯网——每日最新资讯28at.com

E first()
OYC28资讯网——每日最新资讯28at.com

获取最后一个元素
OYC28资讯网——每日最新资讯28at.com

E last()
OYC28资讯网——每日最新资讯28at.com

获取大于指定键的最小键
OYC28资讯网——每日最新资讯28at.com

E higher(E e)
OYC28资讯网——每日最新资讯28at.com

获取小于指定键的最大元素
OYC28资讯网——每日最新资讯28at.com

E lower(E e)
OYC28资讯网——每日最新资讯28at.com

获取大于等于指定键的最小键
OYC28资讯网——每日最新资讯28at.com

E ceiling(E e)
OYC28资讯网——每日最新资讯28at.com

获取小于等于指定键的最大键
OYC28资讯网——每日最新资讯28at.com

E floor(E e)
OYC28资讯网——每日最新资讯28at.com

获取并删除第一个元素
OYC28资讯网——每日最新资讯28at.com

E pollFirst()
OYC28资讯网——每日最新资讯28at.com

获取并删除最后一个元素
OYC28资讯网——每日最新资讯28at.com

E pollLast()
OYC28资讯网——每日最新资讯28at.com

获取前几个元素(inclusive表示是否包含当前元素)
OYC28资讯网——每日最新资讯28at.com

NavigableSetheadSet(E toElement, boolean inclusive)
OYC28资讯网——每日最新资讯28at.com

获取后几个元素(inclusive表示是否包含当前元素)
OYC28资讯网——每日最新资讯28at.com

NavigableSettailSet(E fromElement, boolean inclusive)
OYC28资讯网——每日最新资讯28at.com

获取其中一段元素集合(inclusive表示是否包含当前元素)
OYC28资讯网——每日最新资讯28at.com

NavigableSetsubSet(E fromElement, boolean fromInclusive, E toElement,   boolean toInclusive)
OYC28资讯网——每日最新资讯28at.com

获取其中一段元素集合(左开右开)
OYC28资讯网——每日最新资讯28at.com

SortedSetsubSet(E fromElement, E toElement)
OYC28资讯网——每日最新资讯28at.com

获取前几个元素(不包含当前元素)
OYC28资讯网——每日最新资讯28at.com

SortedSetheadSet(E toElement)
OYC28资讯网——每日最新资讯28at.com

获取后几个元素(不包含当前元素)
OYC28资讯网——每日最新资讯28at.com

SortedSettailSet(E fromElement)
OYC28资讯网——每日最新资讯28at.com

总结

HashSet、LinkedHashSet、TreeSet,这三个常用的Set集合的共同点是都实现了Set接口,所以使用方式都是一样的,使用add()方法添加元素,使用remove()删除元素,使用contains()方法判断元素是否存在,使用iterator()方法迭代遍历元素,这三个类都可以去除重复元素。OYC28资讯网——每日最新资讯28at.com

不同点是:HashSet的关键特性:OYC28资讯网——每日最新资讯28at.com

  1. 是最基础的Set集合,可以去除重复元素。
  2. HashSet是基于HashMap实现的,使用组合的方式,并非继承。
  3. 利用了HashMap的key不重复的特性,而value是一个默认空对象,其他方法也都是使用HashMap实现。

LinkedHashSet的关键特性:OYC28资讯网——每日最新资讯28at.com

  1. LinkedHashSet继承自HashSet,而内部则是采用组合LinkedHashMap的方式实现的。
  2. LinkedHashSet在HashSet功能基础上,增加了按照元素插入顺序或者访问顺序的迭代方式,代价是额外增加一倍的存储空间。
  3. 方法内部都是使用LinkedHashMap实现的。

TreeSet的关键特性:OYC28资讯网——每日最新资讯28at.com

  1. TreeSet是基于TreeMap实现的,也是采用组合的方式。
  2. TreeSet在HashSet功能基础上,可以保证按照元素大小顺序排列,代价是查询、插入、删除接口的时间复杂度从O(1)退化到O(log n)。
  3. 方法内部都是使用TreeMap实现的。

本文链接:http://www.28at.com/showinfo-26-35869-0.htmlJava的Set集合,你真的会用吗?HashSet/TreeSet/LinkedHashSet

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C 语言中 const 和 static 的深入解析

下一篇: 构建实时推荐系统:利用MongoDB和机器学习算法

标签:
  • 热门焦点
  • 影音体验是真的强 简单聊聊iQOO Pad

    大公司的好处就是产品线丰富,非常细分化的东西也能给你做出来,例如早先我们看到了新的vivo Pad2,之后我们又在iQOO Neo8 Pro的发布会上看到了iQOO的首款平板产品iQOO Pad。虽
  • 小米平板5 Pro 12.4简评:多专多能 兼顾影音娱乐的大屏利器

    疫情带来了网课,网课盘活了安卓平板,安卓平板市场虽然中途停滞了几年,但好的一点就是停滞的这几年行业又有了新的发展方向,例如超窄边框、高刷新率、多摄镜头组合等,这就让安卓
  • 微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • 使用LLM插件从命令行访问Llama 2

    最近的一个大新闻是Meta AI推出了新的开源授权的大型语言模型Llama 2。这是一项非常重要的进展:Llama 2可免费用于研究和商业用途。(几小时前,swyy发现它已从LLaMA 2更名为Lla
  • 三分钟白话RocketMQ系列—— 如何发送消息

    我们知道RocketMQ主要分为消息 生产、存储(消息堆积)、消费 三大块领域。那接下来,我们白话一下,RocketMQ是如何发送消息的,揭秘消息生产全过程。注意,如果白话中不小心提到相关代
  • 腾讯盖楼,字节拆墙

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之&ldquo;想重温暴刷深渊、30+技能搭配暴搓到爽的游戏体验吗?一起上晶核,即刻暴打!&rdquo;曾凭借直播腾讯旗下代理格斗游戏《DNF》一
  • 花7万退货退款无门:谁在纵容淘宝珠宝商家造假?

    来源:极点商业作者:杨铭在淘宝购买珠宝玉石后,因为保证金不够赔付,店铺关闭,退货退款难、维权无门的比比皆是。&ldquo;提供相关产品鉴定证书,支持全国复检,可以30天无理由退换货。&
  • ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大&ldquo;烤&rdquo;之下的除了众生,还有各大企业发布的ESG报告。ESG是&ldquo;环境保
  • 网红炒股不为了赚钱,那就是耍流氓!

    来源:首席商业评论6月26日高调宣布入市,网络名嘴大v胡锡进居然进军了股市。在一次财经媒体峰会上,几个财经圈媒体大佬就&ldquo;胡锡进炒股是否知道认真报道&rdquo;展开讨论。有
Top