您现在的位置是:网站首页 > 代码编程 > JAVA开发JAVA开发
【原】HashSet的实现原理,与HashMap有何区别和联系
不忘初心 2019-03-22 围观() 评论() 点赞() 【JAVA开发】
简介:JDk为我们提供了一些常用的数据结构,List、Map、Set这三种是使用最广泛的,List存放连续的数据,并允许为null,Map以键值对的形式存放数据,允许
JDk为我们提供了一些常用的数据结构,List、Map、Set这三种是使用最广泛的,List存放连续的数据,并允许为null,Map以键值对的形式存放数据,允许key和value为null,Set则可以存储无重复的数据。
1、在map中,如果使用了相同的key,后面的value就会将前面的value覆盖掉,这也相当于说是key是唯一的,那这个作用岂不是和Set一样了?
2、这二者之间又有什么区别和联系呢?
3、Java数据结构中,除了数组和链表,似乎也没有什么可以直接和Set进行挂钩呢?
之前的文章中,我们分析了ArrayList的源代码,这次我们同样来分析一下HashSet的源码。
在这之前,先来给大家看一张图:
大家看到了什么?HashMap。
是否有疑惑,为什么初始化HashSet会new一个HashMap呢?莫非底层实现就是HashMap?
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
/**
* Constructs a new set containing the elements in the specified
* collection. The <tt>HashMap</tt> is created with default load factor
* (0.75) and an initial capacity sufficient to contain the elements in
* the specified collection.
*
* @param c the collection whose elements are to be placed into this set
* @throws NullPointerException if the specified collection is null
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* the specified initial capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* the specified initial capacity and default load factor (0.75).
*
* @param initialCapacity the initial capacity of the hash table
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
在它的构造方法中,全部都是初始化一个HashMap,我们暂且先记下来。
而且,从上面的截图中,看到了一个PRESENT变量,这个又是做什么的呢?
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
不知道,没关系,我们也暂且先记下来,继续往下看。
初始化完了,就要来存储数据了,直接去看一下add()方法的代码:
/**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
看到这里,小伙伴们应该已经明白了它为什么在初始化时new一个HashMap了,它直接将我们传进来的数据当做key,而value则是上面提到的PRESENT变量。
这也直接证实了我们上面的猜测:Set的底层实现就是HashMap,充分利用了HashMap中的key不可重复这一特性。
其实到这里基本上已经分析完了,这二者的联系已经一目了然,那我们快速的再将其他常用的方法也都看一遍:
迭代器:
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
Set大小:
/**
* Returns the number of elements in this set (its cardinality).
*
* @return the number of elements in this set (its cardinality)
*/
public int size() {
return map.size();
}
是否为空:
/**
* Returns <tt>true</tt> if this set contains no elements.
*
* @return <tt>true</tt> if this set contains no elements
*/
public boolean isEmpty() {
return map.isEmpty();
}
是否包含指定元素:
/**
* Returns <tt>true</tt> if this set contains the specified element.
* More formally, returns <tt>true</tt> if and only if this set
* contains an element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>.
*
* @param o element whose presence in this set is to be tested
* @return <tt>true</tt> if this set contains the specified element
*/
public boolean contains(Object o) {
return map.containsKey(o);
}
移除元素:
/**
* Removes the specified element from this set if it is present.
* More formally, removes an element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>,
* if this set contains such an element. Returns <tt>true</tt> if
* this set contained the element (or equivalently, if this set
* changed as a result of the call). (This set will not contain the
* element once the call returns.)
*
* @param o object to be removed from this set, if present
* @return <tt>true</tt> if the set contained the specified element
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
清理Set:
/**
* Removes all of the elements from this set.
* The set will be empty after this call returns.
*/
public void clear() {
map.clear();
}
所有的方法都是通过HashMap来实现的,换句话说,所有的操作都是在HashMap上面进行的,HashSet只是做了一层封装,提供了Key的入口,而将Value直接写死了!
看完文章,有任何疑问,请加入群聊一起交流!!!
很赞哦! ()
相关文章
- IntelliJ IDEA 2024.2发布之后强推新UI,如何恢复老的经典UI界面
- Uninstall hasn't detected folder of intelli] lDEA installation. Probablyuninstall.exe was moved from the installation folder.
- 公众号CPS变现新宠:微赚淘客查券返利机器人,开启智能省钱赚钱新时代
- 高返利优惠券公众号推荐
- 返利公众号可信吗安全吗?返利机器人哪个佣金高?
- 唯品会购物返利公众号大揭秘:哪些真正好用的返利公众号?
- 饿了么优惠券免费领取:哪些公众号值得推荐?
- 哪些有用可靠的微信公众号能领淘宝优惠券?
- 微信返利最高的微信号推荐——让你的购物更加实惠!
- 微信返利最高的微信号推荐
标签云
猜你喜欢
- IntelliJ IDEA 2019.2已经可以利用补丁永久破解激活了
- IntelliJ IDEA 2019.3利用补丁永久破解激活教程
- IntelliJ IDEA高版本最灵活的永久破解激活方法(含插件激活,时长你说了算)
- Jetbrains全家桶基于ja-netfilter的最新破解激活详细图文教程
- IntelliJ IDEA 2022.1永久破解激活教程(亲测可用,持续更新)
- 分享几个正版 IntelliJ IDEA 激活码(破解码、注册码),亲测可用,持续更新
- ja-netfilter到底需不需要mymap,2021.3.2版本激活失效?
- 如何激活idea2022.1及以上版本中的插件(亲测可用)
- 【史上最全】IntelliJ IDEA最新2022.1版本安装和激活视频教学(含插件)
- IntelliJ IDEA 2022.2 版本最新2099年永久激活方法,亲测可用,也可以开启新UI了。
站点信息
- 网站程序:spring + freemarker
- 主题模板:《今夕何夕》
- 文章统计:篇文章
- 标签管理:标签云
- 微信公众号:扫描二维码,关注我们