HashSet和CopyOnWriteArraySet
前言
这篇文章的目的如下:
- 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是一样的。
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的更多相关文章
- HashSet和CopyOnWriteArraySet(转载)
前言 这篇文章的目的如下: HashSet是如何保证元素的不重复和无序 HashSet的增删(改查?)原理 CopyOnWriteArraySet支持并发的原理 CopyOnWriteArraySet ...
- HashSet、CopyOnWriteArraySet、ConcurrentSkipListSet源码解析(JDK1.8)
目录 HashSet源码解析 HashSet简单使用的demo HashSet中的变量 HashSet的构造函数 HashSet的add方法 HashSet的iterator方法 HashSet的si ...
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
概要 本章是JUC系列中的CopyOnWriteArraySet篇.接下来,会先对CopyOnWriteArraySet进行基本介绍,然后再说明它的原理,接着通过代码去分析,最后通过示例更进一步的了解 ...
- ArrayList和CopyOnWriteArrayList
这篇文章的目的如下: 了解一下ArrayList的增删改查实现原理 看看为什么说ArrayList查询快而增删慢? CopyOnWriteArrayList为什么并发安全且性能比Vector好 1. ...
- JUC (java.util.concurrent)
1.什么是线程?什么是进程? 2.多线程的状态? public enum State { //6种状态 NEW, RUNNABLE, //可运行 BLOCKED, //阻塞 WAITING, //等待 ...
- CopyOnWriteArrayList的增删改查实现原理
https://www.cnblogs.com/simple-focus/p/7439919.html 篇文章的目的如下: 了解一下ArrayList和CopyOnWriteArrayList的增删改 ...
- Java并发包——线程安全的Collection相关类
Java并发包——线程安全的Collection相关类 摘要:本文主要学习了Java并发包下线程安全的Collection相关的类. 部分内容来自以下博客: https://www.cnblogs.c ...
- Java多线程编程基础知识汇总
多线程简介 多任务 现代操作系统(Windows.Linux.MacOS)都可以执行多任务,多任务就是同时运行多个任务.例如在我们的计算机上,一般都同时跑着多个程序,例如浏览器,视频播放器,音乐播 ...
- 狂神说JUC学习笔记(一)
狂神说JUC的原版笔记: 链接:https://pan.baidu.com/s/12zrGI4JyZhmkQh0cqEO4BA 提取码:d65c 我的笔记在狂神的笔记上增加了一些知识点或者做了些许修改 ...
随机推荐
- Button重写onClick两种方式
实现接口和匿名内部类 下午没课,自己又继续安卓的学习,照着书上做了一个left碎片Button点击后动态加载right碎片布局的Test,准备自己再继续做一个单击左碎片的button1 加载右碎片布局 ...
- 用adb命令查看apk版本
adb devices (显示连接的设备) adb root (获取手机root权限) adb remount (重新挂载系统分区,使系统分区重新可写) adb shell (进入目标设备的L ...
- TCP长连接和短连接的区别
当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需 ...
- MySQL Index Merge Optimization
Index Merge用在通过一些range scans得到检索数据行和合并成一个整体.合并可以通过 unions,intersections,或者unions-intersection运用在底层的扫 ...
- mysql 安装以及配置
MySQL是一个小巧玲珑但功能强大的数据库,目前十分流行.但是官网给出的安装包有两种格式,一个是msi格式,一个是zip格式的.很多人下了zip格式的解压发现没有setup.exe,面对一堆文件一头雾 ...
- React Native学习(八)—— 对接七鱼客服
本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...
- 图表工具--- ECharts.js学习(一) 简单入门
ECharts.js学习(一) 在项目开发的时候,在前端的数据需要用图表的形式展示.网上搜索了一下,发现有几种统计图库.具体有哪几种可以看: 前端开发者常用的9个JavaScript图表库 EChar ...
- 2017-07-01(ifconfig ifdown ifup netstat )
ifconfig 可以查看IP地址与子网掩码 ifdown(禁用网卡) ifdown 网络设备名 ifdown eth0 ifup (启动网卡) ifup 网络设备名 ifup eth0 net ...
- Servlet--继承HttpServlet写自己的Servlet
前面2篇关注的都是Servlet接口,在实际编码中一般不直接实现这个接口,而是继承HttpServlet类.因为j2e的包里面写好了GenericServlet和HttpServlet类来让我们简化编 ...
- linkin大话设计模式--单例模式
linkin大话设计模式 开文前先弱弱的问一句:什么是设计模式?我在研究java2ee的时候有研究过,在学js的时候也有看到.设计模式的概念最早源于建筑设计大师<建筑的永恒算法>一书,它表 ...