前言

这篇文章的目的如下:

  • HashSet是如何保证元素的不重复和无序
  • HashSet的增删(改查?)原理
  • CopyOnWriteArraySet支持并发的原理
  • CopyOnWriteArraySet的增删(改查?)原理

如果不想看分析过程,可直接拉到文章末尾看结论

先来看看 Set接口

public interface Set<E> extends Collection<E> {

    int size();
boolean isEmpty();
boolean contains(Object o);
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean retainAll(Collection<?> c);
boolean removeAll(Collection<?> c);
boolean equals(Object o);
int hashCode();
}

我们从以上接口发现Set并没有get和set方法,也就是没有查和改,为什么呢?原因如下:

  • 因为Set是无序的,没有通过index来进行查询
  • 同样是因为Set是无序的,也就是没有办法通过Index来进行修改

1 HashSet如何保证元素不重复?

要弄清楚HashSet如何保证里面的元素不重复,得从以下两个方面入手:

  • 它底层的存储结构是什么?
  • 插入时是如何判断元素是否存在?

当我们弄清楚上面两个问题之后我们也可以明白HashSet为什么是无序的了。

1)HashSet的底层存储逻辑

且看源码:

public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable{
static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object(); /**
* 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<>();
}
...
}

我们可以看出来HashSet的底层存储结构是一个HashMap,并且HashSet的元素作为该Map的Key进行存储,HashMap的Key的存储是无序并且不可重复,这就解释了HashSet中如何保证元素不重复

2)插入逻辑

public boolean add(E e) {return map.put(e, PRESENT)==null;}

直接put到map当中

3)总结

由以上内容我们可以知道HashSet的底层存储结构是HashMap,并且插入到HashSet中元素作为map的key进行存储,这就保证HashSet的一下特点:

  • HashSet中的元素不重复的
  • HashSet中的元素是无序的

2 HashSet增删(改查?)原理

我们从上一小节了解到HashSet的底层存储结构是HashMap,那么它的增删也就是map的put和remove

1)增

public boolean add(E e) {return map.put(e, PRESENT)==null;}

直接put到map当中

2)删

public boolean remove(Object o) {return map.remove(o)==PRESENT;}

直接在map中移除即可,非常简单

3 CopyOnWriteArraySet为什么能支持并发?

在搞清楚CopyOnWriteArraySet为什么能支持并发 这个问题之前,我们先来想想以下几个问题:

  • HashSet对应的并发类为什么叫CopyOnWriteArraySet,而不是叫CopyOnWriteHashSet呢?
  • CopyOnWriteArraySet和CopyOnWriteArrayList有没有关系?

我想一旦我们弄清楚上面两个问题我们就是知道 CopyOnWriteArraySet为什么能支持并发?

先来看看CopyOnWriteArraySet的部分源码:

public class CopyOnWriteArraySet<E> extends AbstractSet<E>
implements java.io.Serializable {
private static final long serialVersionUID = 5457747651344034263L; private final CopyOnWriteArrayList<E> al; /**
* Creates an empty set.
*/
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
}
...
}

从源码中神奇地发现CopyOnWriteArraySet的底层存储结构竟然是CopyOnWriteArrayList,那么我们就可以知道它的名字的由来了,并且知道它支持并发的原理跟CopyOnWriteArrayList是一样的。

附:CopyOnWriteArrayList原理解析

4 CopyOnWriteArraySet的增删(改查?)原理

1)增

public boolean add(E e) {
return al.addIfAbsent(e);
}

看方法名我们就是如果CopyOnWriteArrayList中不存在某元素才会添加成功

2)删

public boolean remove(Object o) {
return al.remove(o);
}

直接从CopyOnWriteArrayList中移除

5 总结

  • HashSet是如何保证元素的不重复和无序

    答:因为HashSet的底层存储结构是HashMap,并且HashSet中的元素是作为Map的Key存储到Map中,所以HashMap中Key是不重复且无序,所以HashSet中的元素也就是不重复和无序的

  • HashSet的增删(改查?)原理

    HashSet的增删原理很简单,就是map的put和remove,为什么没有改查呢?那是因为HashSet中的元素是无序的,没办法根据索引进行查询和修改

  • CopyOnWriteArraySet支持并发的原理

    CopyOnWriteArraySet之所以叫CopyOnWriteArraySet,是因为它的底层存储结构是CopyOnWriteArrayList,同时也就是保证了它的并发安全性

  • CopyOnWriteArraySet的增删(改查?)原理

    CopyOnWriteArraySet继承了AbstractSet,跟HashSet一样只有增删,没有改查,增删原理也就是调用CopyOnWriteArrayList的增删方法,只不过增的时候需要判断一下List中是否存储该元素

HashSet和CopyOnWriteArraySet(转载)的更多相关文章

  1. HashSet和CopyOnWriteArraySet

    前言 这篇文章的目的如下: HashSet是如何保证元素的不重复和无序 HashSet的增删(改查?)原理 CopyOnWriteArraySet支持并发的原理 CopyOnWriteArraySet ...

  2. HashSet、CopyOnWriteArraySet、ConcurrentSkipListSet源码解析(JDK1.8)

    目录 HashSet源码解析 HashSet简单使用的demo HashSet中的变量 HashSet的构造函数 HashSet的add方法 HashSet的iterator方法 HashSet的si ...

  3. Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet

    概要 本章是JUC系列中的CopyOnWriteArraySet篇.接下来,会先对CopyOnWriteArraySet进行基本介绍,然后再说明它的原理,接着通过代码去分析,最后通过示例更进一步的了解 ...

  4. ArrayList和CopyOnWriteArrayList

    这篇文章的目的如下: 了解一下ArrayList的增删改查实现原理 看看为什么说ArrayList查询快而增删慢? CopyOnWriteArrayList为什么并发安全且性能比Vector好 1. ...

  5. Collection和Map的默认扩容参数

    初始大小:调用无参构造函数时默认的容量 加载因子:超过 (当前容量*加载因子) 时会进行扩容 扩容因子:扩容时增加的容量为 (当前容量*扩容因子)        容器         初始容量    ...

  6. JUC (java.util.concurrent)

    1.什么是线程?什么是进程? 2.多线程的状态? public enum State { //6种状态 NEW, RUNNABLE, //可运行 BLOCKED, //阻塞 WAITING, //等待 ...

  7. CopyOnWriteArrayList的增删改查实现原理

    https://www.cnblogs.com/simple-focus/p/7439919.html 篇文章的目的如下: 了解一下ArrayList和CopyOnWriteArrayList的增删改 ...

  8. Java并发包——线程安全的Collection相关类

    Java并发包——线程安全的Collection相关类 摘要:本文主要学习了Java并发包下线程安全的Collection相关的类. 部分内容来自以下博客: https://www.cnblogs.c ...

  9. Java多线程编程基础知识汇总

    多线程简介 多任务   现代操作系统(Windows.Linux.MacOS)都可以执行多任务,多任务就是同时运行多个任务.例如在我们的计算机上,一般都同时跑着多个程序,例如浏览器,视频播放器,音乐播 ...

随机推荐

  1. Java并发包线程池之Executors、ExecutorCompletionService工具类

    前言 前面介绍了Java并发包提供的三种线程池,它们用处各不相同,接下来介绍一些工具类,对这三种线程池的使用. Executors Executors是JDK1.5就开始存在是一个线程池工具类,它定义 ...

  2. 网络爬虫urllib:request之urlopen

    网络爬虫urllib:request之urlopen 网络爬虫简介 定义:按照一定规则,自动抓取万维网信息的程序或脚本. 两大特征: 能按程序员要求下载数据或者内容 能自动在网络上流窜(从一个网页跳转 ...

  3. jmeter 分布式配置(含参数化问题)

    这次用的是 jmeter 5.1.1  jdk8 调度机: 修改bin目录下jmeter.properties文件 第258行 remote_hosts=192.168.87.34:1856,192. ...

  4. LeetCode_35. Search Insert Position

    35. Search Insert Position Easy Given a sorted array and a target value, return the index if the tar ...

  5. ElasticSearch——索引生命周期管理

    从ES6.6开始,Elasticsearch提供索引生命周期管理功能,索引生命周期管理可以通过API或者kibana界面配置,详情参考[index-lifecycle-management] 本文仅通 ...

  6. Mac更新npm和node版本

    npm: 查看当前版本: npm --version 更新到最新版: sodu npm install npm@latest -g node: 1.查看当前版本: node -v 2.清除npm当前缓 ...

  7. Nginx作为负载均衡把客户端真实IP发送给后端配置

    Nginx作为负载均衡获取到客户端的真实IP,但是后端获取到的IP为nginx负载均衡的IP,需要修改配置使后端获取到客户端的真实IP 修改nginx配置增加3行 proxy_set_header H ...

  8. Flutter 踩坑之build函数返回了null

    今天遇到一个bug,内容都正常显示没问题,但是控制台里报错,如图: 翻译了下,说是函数不能返回空值,搜索了下,网上相同问题的是少写了个return,我检查了下也没发现少return的,后来突然发现if ...

  9. 最新 多益网络java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿. 多益网络等10家互联网公司的校招Offer,因为某些自身原因最终选择了 多益网络.6.7月主要是做系统复习.项目复盘.Le ...

  10. vim文本编辑器的介绍及使用

    (一)什么是vim编辑器 在Linux系统中配置应用服务,实际上就是在修改它的配置文件(配置文件可能有多个,其中包含不同的参数),而且日常工作中也一定免不了编写文档的事情吧,这些都是要通过文本编辑器来 ...