集合类Collenction是java中十分重要的类。
在java中集合类主要包含了List和Set。我们知道List和Set之间有如下的区别:
1:List,有序但是可以有重复的元素。
2:Set,无序但是不可有重复的元素。
现在先把List拎出来剖析一番,List包含两个使用频率颇高的子类,ArrayList和LinkedList。
对于ArrayList和LikedList,我们在实际运用中要学会去选择,选择就要根据它们的特性和某一方面的优势进行依据和判断。
对于ArrayList,在查询和更新方面有优势;对于LinkedList,在删除和添加有优势。
原因就在于ArrayList是一个基于有序数组的数据结构,而对于LinkedList,它是基于链表的数据结构。
数据结构分析:
ArrayList源码
- /**
- * The array buffer into which the elements of the ArrayList are stored.
- * The capacity of the ArrayList is the length of this array buffer. Any
- * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
- * DEFAULT_CAPACITY when the first element is added.
- */
- private transient Object[] elementData;
LinkedList源码
- 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;
- }
- }
next是item的后指针,prev是item的前指针。对于item来说,知道了它的前后的数据,按照顺序排列好,那么这三个元素就构成了LinkedList的链表结构了。
通过构造方法,实现了链表功能。
特性分析:
首先以事实比较下两者添加数据的效率:
- public static void main(String[] args) {
- int num = 1000000;
- ArrayList<Integer> arrayList = new ArrayList<Integer>();
- long arrayStart = System.currentTimeMillis();
- for (int i = 0; i < num; i++) {
- arrayList.add(i);
- }
- long arrayEnd = System.currentTimeMillis();
- long arrayTime = arrayEnd - arrayStart;
- LinkedList<Integer> linkedList = new LinkedList<Integer>();
- long linkedStart = System.currentTimeMillis();
- for (int i = 0; i < num; i++) {
- linkedList.add(i);
- }
- long linkedEnd = System.currentTimeMillis();
- long linkedTime = linkedEnd - linkedStart;
- System.out.println("ArrayList time:" + arrayTime);
- System.out.println("LinkedList time:" + linkedTime);
- }
- ArrayList time:49
- LinkedList time:520
分析add():首先是ArrayList,
- public boolean add(E e) {
- ensureCapacityInternal(size + 1); // Increments modCount!!
- elementData[size++] = e;
- return true;
- }
1.将ArrayList的长度加1.
2.在ArrayList(其实通过源码,发现ArrayList就是一Object个数组)最后赋上我们所添加的值。
再来看看LinkedList,
- public boolean add(E e) {
- linkLast(e);
- return true;
- }
- /**
- * Links e as last element.
- */
- void linkLast(E e) {
- final Node<E> l = last;
- final Node<E> newNode = new Node<>(l, e, null);
- last = newNode;
- if (l == null)
- first = newNode;
- else
- l.next = newNode;
- size++;
- modCount++;
- }
再看下例
- public static void main(String[] args) {
- <span style="white-space:pre"> </span>int num = 1000000;
- <span style="white-space:pre"> </span>ArrayList<Integer> arrayList = new ArrayList<Integer>();
- <span style="white-space:pre"> </span>for (int i = 0; i < num; i++) {
- <span style="white-space:pre"> </span>arrayList.add(i);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>long arrayStart = System.currentTimeMillis();
- <span style="white-space:pre"> </span>for (int i = 0; i < 100; i++) {
- <span style="white-space:pre"> </span>arrayList.add(new Random().nextInt(100), i);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>long arrayEnd = System.currentTimeMillis();
- <span style="white-space:pre"> </span>long arrayTime = arrayEnd - arrayStart;
- <span style="white-space:pre"> </span>LinkedList<Integer> linkedList = new LinkedList<Integer>();
- <span style="white-space:pre"> </span>for (int i = 0; i < num; i++) {
- <span style="white-space:pre"> </span>linkedList.add(i);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>long linkedStart = System.currentTimeMillis();
- <span style="white-space:pre"> </span>for (int i = 0; i < 100; i++) {
- <span style="white-space:pre"> </span>linkedList.add(new Random().nextInt(100), i);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>long linkedEnd = System.currentTimeMillis();
- <span style="white-space:pre"> </span>long linkedTime = linkedEnd - linkedStart;
- <span style="white-space:pre"> </span>System.out.println("ArrayList time:" + arrayTime);
- <span style="white-space:pre"> </span>System.out.println("LinkedList time:" + linkedTime);
- <span style="white-space:pre"> </span>}
- ArrayList time:274
- LinkedList time:1
源码分析,ArrayList
- /**
- * Inserts the specified element at the specified position in this
- * list. Shifts the element currently at that position (if any) and
- * any subsequent elements to the right (adds one to their indices).
- *
- * @param index index at which the specified element is to be inserted
- * @param element element to be inserted
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public void add(int index, E element) {
- rangeCheckForAdd(index);
- ensureCapacityInternal(size + 1); // Increments modCount!!
- System.arraycopy(elementData, index, elementData, index + 1,
- size - index);
- elementData[index] = element;
- size++;
- }
LinkedList:
- /**
- * Inserts the specified element at the specified position in this list.
- * Shifts the element currently at that position (if any) and any
- * subsequent elements to the right (adds one to their indices).
- *
- * @param index index at which the specified element is to be inserted
- * @param element element to be inserted
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public void add(int index, E element) {
- checkPositionIndex(index);
- if (index == size)
- linkLast(element);
- else
- linkBefore(element, node(index));
- }
- /**
- * Inserts element e before non-null Node succ.
- */
- void linkBefore(E e, Node<E> succ) {
- // assert succ != null;
- final Node<E> pred = succ.prev;
- final Node<E> newNode = new Node<>(pred, e, succ);
- succ.prev = newNode;
- if (pred == null)
- first = newNode;
- else
- pred.next = newNode;
- size++;
- modCount++;
- }
通过这种情况的比较,通过arrayCopy明显要对内存的操作更多,开销更大。
光看一个数据添加,不一样的结果。
相比于添加,其余的数据操作也会有不同的效率,通过源码分析,我们可以看出不同的情况下,应该对List有不同的选择。
1. 快速插入,删除元素,队列模型应该使用LinkedList。
2.而对于随机访问元素,此时有下标的数组模型更占优,应该使用ArrayList。
感觉总体思路不是那么清晰,权当作自己学习的笔记,有问题和错误的地方,还请拍砖。