? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?摘自javaguide的集合总体框架图:????????
List:底层基于object[]数组,存储的元素有序、可重复。
Set:底层基于HashMap实现,存储的元素无序,不可重复。
Queue:单端队列,存储的元素有序、可重复。
Map:使用键值对(key-value)存储,key 是无序的、不可重复的。
Set
?接口的实现类,都能保证元素唯一,并且都不是线程安全的。ArrayList三个构造函数:
ArrayList() 默认创建长度为0的数组。
ArrayList(int initialCapacity) 创建指定容量的数组。
? ? ? ? 首次向集合中 add 单个元素时,集合扩容为10,再次扩容为上次的1.5倍。(扩容使用的是位运算,奇数*1.5向下取整)。
? ? ? ? 首次向集合a中 addAll 集合b的元素时,集合a扩容为max(10,集合b的元素个数) ,接着再向集合a中 addAll 集合c的元素时,集合a扩容为max(集合a容量的1.5倍,集合c的元素个数)。
? ? ? ? 位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍:
int newCapacity = oldCapacity + (oldCapacity >> 1);
ArrayList扩容机制描述:
? ? ? ??ArrayList是一个数组结构的存储容器,默认数组长度是10,也可以在初始构建的时候指定长度。随着不断地向容器中添加元素,当达到上限时,ArrayList会自动进行扩容,扩容流程如下:首先会创建一个新的数组,长度为原始数组的1.5倍(使用位运算),然后使用Arrays.copy方法将老数组的元素copy到新数组中,再将需要添加的新元素添加到新数组中。
????????Comparable和Comparator都是接口,都可以用来进行比较、排序,可以将Comparable理解为“内部比较器”,Comparator理解为“外部比较器”。
具体参考这篇文章?Comparable和Comparator区别
? ? ? ??HashMap是一个集合了查询效率和增删效率的容器,内部存的都是一个个键值对,可以通过访问键值对其进行访问和修改。
? ? ? ??HashMap 中的 hash 值是由hash函数产生的,所有键值对存放的位置都是由 hash值和(length-1) 与运算得到的(length必须为2的幂次方,此时与运算等价于对length-1取模)。因此,简单来说hash值就是用来定位某键值对在HashMap中存放的位置的。
? ? ? ? length为2的幂次方可以确保(length-1)的二进制低位都是1,此时hash&(length-1) 等价于 hash%(length-1) ,并且位运算的效率较高。
????????JDK 1.7中在链表中添加元素的方式是头插法,当两个线程同时对HashMap进行扩容操作时,可能会形成环形链表,产生死循环。JDK 1.7中采用了尾插法来避免链表导致,从而避免产生环形链表。
? ? ? ? 具体来说:HashMap扩容时,会将旧HashMap的数据移植到 扩容的新HashMap中,而由于链表的插入方式是头插法,a->b->c 会变成 c->b->a ,旧线程仍然认为a节点后面是b,而b节点后面已经是a了,这里就会产生死循环。
//hashMap计算hash值
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//而hashtable直接使用hashcode值作为最终的hash值
? ? ? ? 当我们将对象加入HashSet时,HashSet会计算该对象的hashcode值,并与HashSet中其他对象作比较:若没有hashcode相同的对象,则该对象不重复,允许加入;若有hashcode相同的对象,还需要使用equals()方法检查两对象是否真的相同,如果相同则不允许加入该对象。
ps: