集合的存储当中,有数组,散列表……的形式。
List,ArrayList 等集合,存储数据是有序的,并且数据可以重复。
底层是以数组形式存储的,默认的数组的大小是10。
扩容机制:如果该集合设置了大小,则集合扩容会在超过该集合设置的大小后进行扩容,扩容算法 是 原数组大小+1+原数组大小/2
例如 List list = new ArrayList(10); 如果添加数组长度超过10个,则进行扩容,10+1+10/2=16 第一次扩容长度将边为16
Map,HashMap 等集合,它的值允许有null,存储数据无序。
底层存储是以数组加链表的形式进行存储的,数组默认大小是16.
扩容机制:集合扩容因子0.75,如果超过原数组长度的75%就会扩容,扩容算法:原数组长度*2
例如:Map map = new HashMap(10);如果添加到该数组中的长度超过 10*0.75 数组将进行扩容,扩容长度为 10*2 ,第一次扩容为20
LinkedList 是一个双向链表,没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增。
分配内存空间不是必须是连续的;
插入、删除操作很快,只要修改前后指针就OK了,时间复杂度为O(1);
访问比较慢,必须得从第一个元素开始遍历,时间复杂度为O(n);
Set,HashSet等集合,底层是以HashMap进行存储的,所以存储的值时不重复的。犹豫HashMap存储的时,会根据key的hashCode的值来确定存储的位置,所以存储是无序的。
扩容机制同HashMap扩容
ConcurrentHashMap :
在hashMap的基础上,ConcurrentHashMap将数据分为多个segment,默认16个(concurrency level),然后每次操作对一个segment加锁,避免多线程锁得几率,提高并发效率.
1)经过4.2的分析,我们知道ConcurrentHashMap对整个数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的syn关键字锁的粒度更精细了一些,并发性能更好,而HashMap没有锁机制,不是线程安全的。
(2)HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。
扩容机制 跟HashMap相同。
ConcurrentHashMap的put方法被代理到了对应的Segment(定位Segment的原理之前已经描述过)中。与JDK6不同的是,JDK7版本的ConcurrentHashMap在获得Segment锁的过程中,做了一定的优化 - 在真正申请锁之前,put方法会通过tryLock()方法尝试获得锁,在尝试获得锁的过程中会对对应hashcode的链表进行遍历,如果遍历完毕仍然找不到与key相同的HashEntry节点,则为后续的put操作提前创建一个HashEntry。当tryLock一定次数后仍无法获得锁,则通过lock申请锁。