集合 List
特点:有序(存储顺序和取出顺序一致),可重复
ArrayLIst 数据结构是数组,线程不安全
LinkedList 数据结构是链表,线程不安全(双向链表方便实现往前遍历)
Vector 数据结构是数组,线程安全
copyOnWriteList 并发容器,线程安全(COW设计模式)
ArrayList解析
- ArrayList底层为一个数组,内部有扩容的概念,初始容量为10,每次扩容增加原先容量的一半(1.5倍)实现了”动态“增长
- ArrayList是基于动态数组实现的,在增删的时候,需要数组的拷贝复制
- 删除元素时不会减少容量,若希望减少则调用trimToSize()
- 它不是线程安全的,能存放null
- Add(E e)方法
首先检查一下数组的容量是否足够,足够则直接添加,不够扩容,扩容到原来的1.5倍,第一次扩容后,如果容量还是小于minCapacity,就将容量扩容为minCapacity - Add(int index,E e)
检查角标是否越界,空间检查,如果有需要进行扩容,调用arraycopy()来进行插入(在高性能的jvm中,会对这种intrinsic method进行特殊优化处理,达到高效执行数组拷贝) - get(int index)以及set(int index,E e)
检查角标,返回元素/替代元素(会返回旧值) - remove(int index)
检查角标,计算出需要移动的个数,并移动、删除元素,elementData[—size] = null; 设置为null,让GC回收
Vector
- Vector底层也是数组,它是线程安全
- 如果想要ArrayList实现同步,可以使用Collections的方法:List list = Collections.synchronizedList(new ArrayList(…));,就可以实现同步
- Vector扩容原来的1倍,arrayList扩容原来的0.5倍
LinkedLIst
- 底层是双向链表
- linkedList实现了deque接口,我们可以操作linkedList像操作队列和栈一样
- add(E e)方法
往链表最后添加元素
final node temp = last;
final newNode = new Node();
last = newNode;
l.next = newNode;
Size++;
- remove(Object o)
- get(int index) 、set(int index,E e)
通过传入的下标与size对比,下标小于长度的一半,就从头遍历,否则从尾遍历
copyOnWriteList
1.Hashtable、Vector加锁的粒度大(直接在方法声明处使用synchronized)
2.ConcurrentHashMap、CopyOnWriteArrayList加锁粒度小(用各种的方式来实现线程安 全,比如我们知道的ConcurrentHashMap用了cas锁、volatile等方式来实现线程安全…)
3.JUC下的线程安全容器在遍历的时候不会抛出ConcurrentModificationException异常
- CopyOnWriteArrayList是线程安全容器(相对于ArrayList),底层通过复制数组的方式来实现。
- CopyOnWriteArrayList在遍历的使用不会抛出ConcurrentModificationException异常,并且遍历的时候就不用额外加锁
- 元素可以为null