ArrayList
1.ArrayList继承了List/RandomAccess/Cloneable/serializable 接口,内部维护一个数组用来存放对象。
2.RandomAccess 接口,用于标明实现该接口的List支持快速随机访问,也就是For循环速度会比用iterator要快。LinkedList 没有实现该接口,底层结构是双向链表适合用iterator来遍历。
3.ArrayList 默认初始容量是10,也可以在构造方法中指定初始容量,每次扩容总容量增加一半。
HashMap
1.底层结构是数组加链表,每一个数组元素都是一个封装了key 和value 的单向链表Node,通过特定函数对Key 的hash 值进行运算得到数组下标。JDK1.8以后,当链表节点数量达到8个时,链表会自动转换成红黑树,以增加查找效率。
int index=hash(key)&(threshold-1);
static final int hash(Object key){
int h;
return (key==null)?0:(h=key.hashCode())^(h>>>16);}
2.默认容量是16,数据长度大于负载因子*总容量时会扩容,每扩容一次加倍。构造方法里面可以传入一个参数来初始化数组长度,该算法为一个位移算法。
3.链表添加新元素时,JDK1.8之前为头插法,从1.8开始为尾插法。在HashMap扩容的时候,头插法会改变链表中节点的顺序,在多线程的情况下容易造成链表成环的问题。尾插法不会改变链表节点的顺序,所以不存在这个问题
4.ConcurrentHashMap ,多线程推荐使用。在put 和remove 等方法中使用了sychornized 对象锁,用volatile关键字修饰关键变量,保证线程安全。
5.LinkedHashMap 中另外维护了一个双向队列,在构造方法中传入了一个参数,用来指定遍历的规则(按照插入顺序或者查询元素排序)。
6.HashSet 持有一个HashMap 对象,add 对象时,把该对象当作key,所有的value 都是同一个static final object。