HashMap原理,Hash冲突,同步集合,并发集合,线程安全集合及实现原理

HashMap原理

HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。HashMap储存的是键值对,HashMap很快。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
通过hash的方法,put、get存储和获取对象。

HashMap加载因子

若加载因子越大,填满的元素越多,好处是,空间利用率高了,但冲突的机会加大了.链表长度会越来越长,查找效率降低。
反之,加载因子越小,填满的元素越少,好处是冲突的机会减小了,但空间浪费多了.表中的数据将过于稀疏(很多空间还没用,就开始扩容了)
冲突的机会越大,则查找的成本越高. 因此,必须在 "冲突的机会"与"空间利用率"之间寻找一种平衡与折衷.
这种平衡与折衷本质上是数据结构中有名的"时-空"矛盾的平衡与折衷.
如果机器内存足够,并且想要提高查询速度的话可以将加载因子设置小一点;相反如果机器内存紧张,并且对查询速度没有什么要求的话可以将加载因子设置大一点。不过一般我们都不用去设置它,让它取默认值0.75就好了。

在构造HashMap的时候可以指定加载因子和初始容量,默认初始容量为16,默认加载因子为0.75,每次扩容为当前的2倍。
提前预知HashMap的大小能够提升性能,因为自动扩容的时候会暂用资源。

Hash冲突

通过哈希函数把键映射成索引,在多个键映射的索引值出现相同时,这就是Hash冲突也叫哈希碰撞。
Key的hashcode一致可以理解为哈希冲突,哈希冲突会影响查询的效率。

解决Hash冲突

1、开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
2、拉链法
3、再哈希
4、建立公共溢出区(待深究)
参考:https://blog.csdn.net/yeiweilan/article/details/73412438

同步集合

1、Hashtable 是一个散列表,它存储的内容是键值对(key-value)映射。Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外,Hashtable中的映射不是有序的

2、Vector 是在 java 中可以实现自动增长的对象数组,vector类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的。Vector 是同步访问的,Vector 包含了许多传统的方法,这些方法不属于集合框架

并发集合 (以下为java.util.concurrent - Java并发工具包中的同步集合)

1、ConcurrentHashMap 支持完全并发的检索和更新,所希望的可调整并发的哈希表。此类遵守与 Hashtable 相同的功能规范,并且包括对应于 Hashtable 的每个方法的方法版本。不过,尽管所有操作都是线程安全的,但检索操作不必锁定,并且不支持以某种防止所有访问的方式锁定整个表。此类可以通过程序完全与 Hashtable 进行互操作,这取决于其线程安全,而与其同步细节无关。

2、ConcurrentSkipListMap 是基于跳表的实现,也是支持key有序排列的一个key-value数据结构,在并发情况下表现很好,是一种空间换时间的实现,ConcurrentSkipListMap是基于一种乐观锁的方式去实现高并发。

3、ConCurrentSkipListSet (在JavaSE 6新增的)提供的功能类似于TreeSet,能够并发的访问有序的set。因为ConcurrentSkipListSet是基于“跳跃列表(skip list)”实现的,只要多个线程没有同时修改集合的同一个部分,那么在正常读、写集合的操作中不会出现竞争现象。

4、CopyOnWriteArrayList 是ArrayList 的一个线程安全的变形,其中所有可变操作(添加、设置,等等)都是通过对基础数组进行一次新的复制来实现的。这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法更 有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。“快照”风格的迭代器方法在创建迭代器时使用了对数组状态的引用。此数组在迭代器的生存期内绝不会更改,因此不可能发生冲突,并且迭代器保证不会抛出 ConcurrentModificationException。自创建迭代器以后,迭代器就不会反映列表的添加、移除或者更改。不支持迭代器上更改元素的操作(移除、设置和添加)。这些方法将抛出 UnsupportedOperationException。

5、CopyOnWriteArraySet 线程安全的无序的集合,可以将它理解成线程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表(HashMap)”实现的,而CopyOnWriteArraySet则是通过“动态数组(CopyOnWriteArrayList)”实现的,并不是散列表。

6、ConcurrentLinkedQueue 是一个基于链接节点的、无界的、线程安全的队列。此队列按照 FIFO(先进先出)原则对元素进行排序,队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列检索操作从队列头部获得元素。当许多线程共享访问一个公共 collection 时,ConcurrentLinkedQueue 是一个恰当的选择,此队列不允许 null 元素。

注:ArrayList和HashMap是非并发集合,迭代时不能进行修改和删除操作
注:CopyOnWriteArrayList和CopyOnWriteArraySet,最适合于读操作通常大大超过写操作的情况

线程安全集合及实现原理

HashMap线程是不安全的,如需线程安全使用Collections类的synchronizedMap(),建议在初始化时就使用。

参考文章:

https://blog.csdn.net/donghejk/article/details/83781932
http://www.cnblogs.com/yangecnu/p/Introduce-Hashtable.html
https://yikun.github.io/2015/04/01/Java-HashMap工作原理及实现/
https://blog.csdn.net/bigtree_3721/article/details/51303914

你可能感兴趣的:(java,基础)