Java学习笔记——容器之List
来源:互联网 发布:淘宝上论文发表靠谱吗 编辑:程序博客网 时间:2024/06/11 08:25
本文主要是分析实现List接口的ArrayList、LinkedList、Vector、Stack的源码。
1. ArrayList
ArrayList是使用Object数组保存数据的,并且加上了transient关键字,所以在ArrayList序列化时,elementData不会直接被序列化
transient Object[] elementData;ArrayList有3种构造函数:第1种是无参的,这时候elementData是一个长度为0的空数组, 当往List里添加元素时才会为elementData分配空间;第2种是传入initialCapacity的参数,会为elementData分配initialCapacity的空间;第3种是传入List,此时会用
Arrays.copyOf拷贝传入list中的数据给elementData。
ArrayList中数组采用1.5倍的增长方式的,如果增长后空间还不够,则数组长度取当前要插入数据总长度,增长后将原来的数据拷贝到新生成的数组中,代码如下:
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
2.LinkedList
LinkedList是采用链表存储数据的List,有以下三个成员变量,分别表示长度、链表头、链表尾。
transient int size = 0; transient Node<E> first; transient Node<E> last;
其中,Node的定义如下:
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }LinkedList除了支持List接口的方法外,还支持peek、poll、push、pop等方法,只要对于数据结构有一定了解的同学都能够完成类似代码的编写,因此在此就不做过多的介绍。 另外,在LinkedList的remove和Clear方法中,都有将node的item、next、prev置为null,以便GC回收。
public void clear() { // Clearing all of the links between nodes is "unnecessary", but: // - helps a generational GC if the discarded nodes inhabit // more than one generation // - is sure to free memory even if there is a reachable Iterator for (Node<E> x = first; x != null; ) { Node<E> next = x.next; x.item = null; x.next = null; x.prev = null; x = next; } first = last = null; size = 0; modCount++; }
3.Vector
vector同ArrayList一样,都是采用数组来存储数据,但vector与ArrayList有两点不同:
(1)Vector在public的方法上使用了 synchronized 关键字来保证同步
(2)Vector在构造时可以传递一个长度的增长量capacityIncrement,如果该值不小于0则每次按该值增长,否则按2倍增长。
4.Stack
Stack继承自Vector,只不过多了peek、push、pop三个方法。
上述的ArrayList、LinkedList、Vector、Stack,ArrayList和LinkedList都是非线程安全的,因此要使用线程安全的List,可以调用Collections.synchronizedList方法,它会将传入的List包装成SynchronizedList,是线程安全的,代码如下:
public static <T> List<T> synchronizedList(List<T> list) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list)); }
SynchronizedList继承自SynchronizedCollection,它有一个成员变量mutex作为同步的信号量,在实现的List的每一个方法中,采用synchronized关键字获取mutex,然后再调用包装前的list相应方法。
5.CopyOnWriteArrayList
CopyOnWriteArrayList也是采用数组来存储数据的,但是它每次新增数据时都会重新生成一个新的数组,因此CopyOnWriteArrayList适用于读多写少的场景。与上述几个类不同,它位于concurrent包,通过ReentrantLock类型的成员变量lock实现线程安全,在add、remove、retain、set等方法对数据进行操作之前,先调用ReentrantLock的lock()方法获取锁,操作完成之后再调unlock释放锁。如Add方法的源码如下所示:
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
- Java学习笔记——容器之List
- Java容器学习之——List
- STL学习笔记— —容器list
- JAVA学习笔记——容器之Map
- Java学习笔记——容器之Set
- Java学习笔记——容器之Queue
- c++学习笔记之vector容器与list容器
- 学习笔记之--java容器
- Java容器学习之List接口
- 《STL源码剖析》学习笔记之三——序列式容器(list和vector)
- STL学习笔记——序列式容器list
- STL学习笔记5— —容器list
- JAVA容器之List
- Java学习笔记之List
- STL学习系列之三——list序列容器
- Java容器——JSTL学习笔记
- Java容器——JSTL学习笔记
- Java学习笔记——容器
- 【Scikit-Learn 中文文档】神经网络模块(监督的)- 监督学习
- spring boot实战(第五篇)配置源码解析
- 邻接矩阵实现的无向图
- @Responsebody注解的作用
- Linux Kernel 学习笔记9:内核与用户层通信之netlink
- Java学习笔记——容器之List
- PAT乙级1042 字符统计
- Ubuntu16.04中搜狗输入法的安装
- ASM 的failgroup组测试
- leetcode 378. Kth Smallest Element in a Sorted Matrix
- javascript的调试技巧
- 开发中遇到的问题汇总
- 2017冬《3D科技作图》学习班上海开课啦!
- 成为Java顶尖程序员 ,看这9本书就够了