关于HashSet与HashMap的区别及说明

 更新时间:2023年07月26日 09:42:11   作者:huhahuha_  
这篇文章主要介绍了关于HashSet与HashMap的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

HashSet与HashMap的区别

HashSet 集合不允许存储相同的元素, 它底层实际上使用 HashMap 来存储元素的,不过关注的只是key元素, 所有 value元素默认为 Object类对象.

HashSet源码如下

HashSet 的构造方法

//HashSet底层用来存储元素的结构,实际上使用HashMap来存储
private transient HashMap<E,Object> map;
//HashMap中的value值,HashSet只关注key值,所以所有的value值都为Object对象
private static final Object PRESENT = new Object();
//HashSet的无参构造,直接创建了一个HashMap对象
public HashSet() {
        map = new HashMap<>();
}
//指定初始化容量和负载因子
public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
}
//给定初始化容量
public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
}
public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
}

可以看到 HashSet的构造方法底层都是调用 HashMap的构造方法, 所以HashSet底层实际上是使用 HashMap 来作为存储结构.

当使用无参构造创建 HashSet对象时, 其实调用了 HashMap的无参构造创建了一个 HashMap对象, 所以 HashSet 的初始化容量也为16, 负载因子也为 0.75.

再来看看 HashSet 的 add() 方法的实现:

可以看到 HashSet 的 add() 方法底层实际也是调用了 HashMap 的 put() 方法, 这里的key为我们传入的将要添加到 set集合中的元素, 而value值则为 PERSENT,其实就是上面分析的 HashSet类中的一个静态字段, 默认为 Object对象.

HashSet并不关注value元素, 只使用 HashMap来存储 key元素, 这就使得 HashSet判断元素相等的条件与 HashMap中 key相等的条件其实是一样的, 两个元素的 hashCode值相同且通过equals()方法比较返回 true.

所以HashSet应该重写 equals()和hashCode()方法, 两个元素的 HashCode相同, 保证通过equals() 方法比较返回 true.

总结一下HashSet和HashMap的区别

(1)HashSet实现了Set接口, 仅存储对象; HashMap实现了 Map接口, 存储的是键值对.

(2)HashSet底层其实是用HashMap实现存储的, HashSet封装了一系列HashMap的方法. 依靠HashMap来存储元素值,(利用hashMap的key键进行存储), 而value值默认为Object对象. 所以HashSet也不允许出现重复值, 判断标准和HashMap判断标准相同, 两个元素的hashCode相等并且通过equals()方法返回true.

HashSet与HashMap的关系

HashSet作为一种最简单的java集合类,真的可以用三句话来概括一下:

第一句:存放不重复的数据。第二句:底层基于hash表实现。第三句:内部基于HashMap。

这也就是说,你想要完完全全彻彻底底地把HashSet吃透,就一定要先吃透HashMap。这篇文章将带着你从特点到存储,再到最后的实现,从源码角度来分析一下。

认识

HashSet其实就是一个没有重复数据的集合,基本用法很简单,我们直接给个例子。

以上只是列出了其最简单的用法。下面我们看看其继承关系。

HashSet主要继承了三个接口Serializable、Cloneable、Set,并且实现了抽象类AbstractSet。

我们直接看看源码:

学过HashMap的人应该都知道HashMap实现的是Map接口,而HashSet是Set接口。

下面我们就从源码的角度来分析一下HashSet。

源码分析

1、参数变量

这里有个问题,那就是既然HashSet只使用到了HashMap的key,为什么不使用null来充当HashMap的value,而使用了PRESENT这个对象呢?

答:想要深入这个问题,我们还需要深入到源码中看看:

以上两个是增删方法,在add一个元素的时候,其实调用的就是map.put(e, PRESENT)==null,HashMap在put元素的时候会出现两种情况:

情况一:put的元素是新的,那么map.put会发现key没有,那么直接插入即可。return结果为true。

情况二:put的元素是旧的,那么map.put会发现key已有,则直接返回相应的value,也就是PRESENT,PRESENT不等于null,return的也就是false了,表示HashSet插入失败。如果我们这里使用null为map.put的参数呢?直接返回相应的value,也就是null,这时候null==null是true。竟然返回了true。很明显就是错误的返回结果呀。

这其实也是去重复的原理。对于删除方法其实也是一样的。

2、构造函数

HashSet提供的构造方法很多,有5个,在这里我想说明的是每一种构造方法,其实都是创建的HashMap。这也证明了我们文章开头提到的内部基于HashMap。

3、其他方法

增删方法我们已经提到了,在这里我们主要看一下其他方法。

上面的方法还包含了遍历元素的方式。

HashSet就是这么简单,源码里面几乎所有的方法都是HashMap实现的。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java多线程应用实现方法

    java多线程应用实现方法

    以前没有写笔记的习惯,现在慢慢的发现及时总结是多么的重要了,呵呵。虽然才大二,但是也快要毕业了,要加油
    2012-11-11
  • 详解springcloud之服务注册与发现

    详解springcloud之服务注册与发现

    本次分享的是关于springcloud服务注册与发现的内容,将通过分别搭建服务中心,服务注册,服务发现来说明,非常具有实用价值,需要的朋友可以参考下
    2018-06-06
  • 详解Mybatis多参数传递入参四种处理方式

    详解Mybatis多参数传递入参四种处理方式

    这篇文章主要介绍了详解Mybatis多参数传递入参四种处理方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • 解析Java编程之Synchronized锁住的对象

    解析Java编程之Synchronized锁住的对象

    这篇文章主要介绍了解析Java编程之Synchronized锁住的对象,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • springboot整合shiro实现登录验证授权的过程解析

    springboot整合shiro实现登录验证授权的过程解析

    这篇文章主要介绍了springboot整合shiro实现登录验证授权,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-01-01
  • SpringBoot之Order注解启动顺序说明

    SpringBoot之Order注解启动顺序说明

    这篇文章主要介绍了SpringBoot之Order注解启动顺序说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • easycode配置成mybatis-plus模板的实现方法

    easycode配置成mybatis-plus模板的实现方法

    本文主要介绍了easycode配置成mybatis-plus模板的实现方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 工作中Java集合的规范使用操作详解

    工作中Java集合的规范使用操作详解

    这篇文章主要为大家详细介绍了工作中Java集合使用时需要注意的规范,文中的示例代码讲解详细,对我们使用Java集合有一定的帮助,感兴趣的可以了解一下
    2022-11-11
  • java实现找出两个文件中相同的单词(两种方法)

    java实现找出两个文件中相同的单词(两种方法)

    这篇文章主要介绍了java实现找出两个文件中相同的单词(两种方法),需要的朋友可以参考下
    2020-08-08
  • Java代理深入讲解之静态代理

    Java代理深入讲解之静态代理

    这篇文章主要给大家介绍了关于Java静态代理的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09

最新评论