Map介绍,以及map的底层;list介绍,以及list底层

java.util 中的集合类包含 Java 中某些最常用的类。最常用的集合类是 List 和 Map。
List的实现类分别有ArrayList,LinkedList,Vector。
ArrayList:相当于是new了个Object的类型的数组,默认值是10,底层数据结构使数组结构,查询速度快,增删改慢。
LinkedList:底层使用链表结构,增删速度快,是根据地址传递的,两个之间有相互关联的地址:查询稍慢,删除新增快,LinkedList也有get()取值方法,但是它是从第一个查询完所有的之后,在从中用get()取值。
Vector:底层是数组结构,线程同步ArrayList是线程不同步;
ArrayList当初始化容量超过10时,会重新new一个相当于之前150%的集合 ,把原来的东西放入这150%中;Vector:当容量超过10时,则会new一个200%的集合放进去,浪费内存。
CopyOnWriteArrayList:在写时拷贝,也就是如果需要对CopyOnWriteArrayList的内容进行改变,首先会拷贝一份新的List并且在新的List上进行修改,最后将原List的引用指向新的List。使用CopyOnWriteArrayList可以线程安全地遍历,因为如果另外一个线程在遍历的时候修改List的话,实际上会拷贝出一个新的List上修改,而不影响当前正在被遍历的List。

Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。从概念上而言,您可以将 List 看作是具有数值键的 Map。而实际上,除了 List 和 Map 都在定义 java.util 中外,两者并没有直接的联系。
HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。
Entry就是数组中的元素,每个Entry其实就是一个key-value对,它持有一个指向下一个元素的引用,这就构成了链表。
HashMap在底层将key-value当成一个整体进行
处理,这个整体就是一个Entry对象。HashMap底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据hash算法来决定其在数组中的存储位置,再根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。

默认是构建一个初始容量为16,负载因子为0.75的HashMap。也就是说,默认情况下,数组大小为16,那么当HashMap中元素个数超过160.75=12的时候,就把数组的大小扩展为 216=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。
HashTable与HashMap大体一致,但是在操作HashTable时会默认加上一个同步锁,其它进程要操作此对象。只能等本次操作完成后解开同步锁。
ConcurrentHashMap遵从了和Hashtable一样的规范,这里指的是线程安全的规范,但是其底层的实现与Hashtable并不一致。ConcurrentHashMap底层采用的锁机制,执行put方法的线程会获得锁,只有当此线程的put方法执行结束后才会释放锁,根据多线程的知识,获得锁的线程会通知其他试图操作put方法的线程,并通知其他线程出于等待状态,直到释放锁后,其他线程才会去重新竞争锁。这一点保证了ConcurrentHashMap的线程安全。
HashMap采用链地址法解决哈希冲突,多线程访问哈希表的位置并修改映射关系的时候,后执行的线程会覆盖先执行线程的修改,所以不是线程安全的。
Hashtable采用synchronized关键字解决了并发访问的安全性问题但是效率较低。
ConcurrentHashMap其实是HashTable的升级版,使用了线程锁分段技术,每次访问只允许一个线程修改哈希表的映射关系,所以是线程安全的。

猜你喜欢

转载自blog.csdn.net/weixin_45031351/article/details/91788821