ArrayList 与 LinkedList的区别
今天查看源码,分析一下两者的异同。外加阐述内部类。
内部类参考官方文档,地址如下:
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
本文思路是从两者的构造函数着手,之后是add()分析。
1.构造函数
1 public class Test { 2
// 下面两行不多说,就是创建List,这时注意一点,在构造函数中,尽量指定集合的大小。你可能会问,不指定的话,不是会有默认的size吗?完全正确。
// 但是当程序指定默认的size后,当集合变大需要扩容的时候,会阻碍一部分性能,所以如果能够预知list的size,尽量指定合理的大小。 3 List<String> aList = new ArrayList<String>();
// List<String> aList = new ArrayList<String>(16); 4 List<String> bList = new LinkedList<String>();
// List<String> bList = new LinkedList<String>(16); 5 } 6 7 /** 8 * Constructs an empty list with the specified initial capacity. 9 * 10 * @param initialCapacity the initial capacity of the list 11 * @throws IllegalArgumentException if the specified initial capacity 12 * is negative 13 */
// 带有size大小的初期化方法,没什么可说的。判断size大小
14 public ArrayList(int initialCapacity) { 15 if (initialCapacity > 0) { 16 this.elementData = new Object[initialCapacity]; 17 } else if (initialCapacity == 0) { 18 this.elementData = EMPTY_ELEMENTDATA; 19 } else { 20 throw new IllegalArgumentException("Illegal Capacity: "+ 21 initialCapacity); 22 } 23 } 24 25 /** 26 * Constructs an empty list with an initial capacity of ten. 27 */
// 默认构造器 28 public ArrayList() { 29 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 30 }
/**
* Constructs an empty list.
*/
public LinkedList() {
}
2. ArrayList的add()方法
1 /** 2 * Appends the specified element to the end of this list. 3 * 4 * @param e element to be appended to this list 5 * @return <tt>true</tt> (as specified by {@link Collection#add}) 6 */ 7 public boolean add(E e) { 8 // 扩容 9 ensureCapacityInternal(size + 1); // Increments modCount!! 10 // 在最后位置赋值 11 elementData[size++] = e; 12 return true; 13 }
1 private void ensureCapacityInternal(int minCapacity) { 2 // 判断list是否为空,如果为空,则为list指定默认容量,DEFAULT_CAPACITY的值是10 3 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 4 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 5 } 6 7 // 进行扩容 8 ensureExplicitCapacity(minCapacity); 9 } 10 11 private void ensureExplicitCapacity(int minCapacity) {
// 这个变量记录list结构扩容的次数,更具体的用处是什么,稍后研究。如果有想法的朋友,一起探讨 12 modCount++; 13 14 // overflow-conscious code 15 if (minCapacity - elementData.length > 0) 16 grow(minCapacity); 17 }
1 /** 2 * Increases the capacity to ensure that it can hold at least the 3 * number of elements specified by the minimum capacity argument. 4 * 5 * @param minCapacity the desired minimum capacity 6 */ 7 private void grow(int minCapacity) { 8 // overflow-conscious code 9 int oldCapacity = elementData.length; 10 int newCapacity = oldCapacity + (oldCapacity >> 1); 11 if (newCapacity - minCapacity < 0) 12 newCapacity = minCapacity; 13 if (newCapacity - MAX_ARRAY_SIZE > 0) 14 newCapacity = hugeCapacity(minCapacity); 15 // minCapacity is usually close to size, so this is a win:
// 大家在这里可以按到ArrayList使用的是数组结构,当元素增加或减少时会将数组进行复制,因此查询速度快,增加或删除时,相对较慢。
16 elementData = Arrays.copyOf(elementData, newCapacity); 17 } 18 19 private static int hugeCapacity(int minCapacity) { 20 if (minCapacity < 0) // overflow 21 throw new OutOfMemoryError(); 22 return (minCapacity > MAX_ARRAY_SIZE) ? 23 Integer.MAX_VALUE : 24 MAX_ARRAY_SIZE; 25 }
3. LinkedList的add()方法
1 public boolean add(E e) { 2 linkLast(e); 3 return true; 4 } 5 6 /** 7 * Links e as last element. 8 */ 9 void linkLast(E e) { 10 final Node<E> l = last;
// 封装了数据e的新节点 11 final Node<E> newNode = new Node<>(l, e, null); 12 last = newNode;
// 如果是null表明链表中数据为空,那么将新节点设置为首节点,如果不为空,则增加的最后一个节点。
// 因此在查询的时候,需要从头一直查到最后一个,效率较慢,但是面对增加删除时,只需更该其中的关联的前后节点,不必进行数组的复制,因此性能得以提升。 13 if (l == null) 14 first = newNode; 15 else 16 l.next = newNode; 17 size++; 18 modCount++; 19 }
我们在查看Node<E>这个类时,会发现它是个静态内部类。
1 private static class Node<E> { 2 E item; 3 Node<E> next; 4 Node<E> prev; 5 6 Node(Node<E> prev, E element, Node<E> next) { 7 this.item = element; 8 this.next = next; 9 this.prev = prev; 10 } 11 }
内部类有什么作用,以前为什么会有静态内部类和非静态内部类呢?
我呢就不做搬运工了,在此呢推荐个官方文章,https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
里面详细阐述了内部类的分类,使用的好处等。
努力到无能为力,奋斗到感动上天!