ArrayList LinkedList Vector
ArrayList与LinkedList
ArrayList 通过数组实现,LinkedList 通过双向链表实现
get/set:ArrayList直接通过下标在数组中取,LinkedList需要从头/尾遍历到index
add/remove:ArrayList需要将index之后的元素都复制一遍,如果需要扩容需要将原数组所有元素复制到新数组
(如果一个包含大量元素的ArrayList对象,数组扩容1.5倍,那么最终将有很大的空间会被浪费掉,调用trimToSize方法去掉浪费掉的空间)
LinkedList需要从头/尾遍历到该元素并操作前后节点
get
/** * ArrayList get * 直接通过下标在数组中取 */ public E get(int index) { rangeCheck(index); return elementData(index); } E elementData(int index) { return (E) elementData[index]; } /** * LinkedList get * 从头/尾遍历到index */ public E get(int index) { checkElementIndex(index); return node(index).item; } Node<E> node(int index) { if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
set
/** * ArrayList set * 同get */ public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } /** * LinkedList * 同get */ public E set(int index, E element) { checkElementIndex(index); Node<E> x = node(index); E oldVal = x.item; x.item = element; return oldVal; }
add
/** * ArrayList数组扩容 * 1.需求容量 <= elementData.length, 不需要扩容 * 2.newCapacity = 1.5*oldCapacity 或 需求容量 * 3.扩容之后, 原数组元素复制到新数组 */ private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private void ensureExplicitCapacity(int minCapacity) { modCount++; if (minCapacity - elementData.length > 0) grow(minCapacity); } 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); } /** * ArrayList add(e) * 1.数组扩容(需要的话) * 2.添加e */ public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } /** * ArrayList add(index, e) * 1.数组可能要扩容 * 2.index之后的元素复制一遍到index+1之后 * 3.elementData[index] = e; */ 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 add(e) * 直接与最后一个元素互相添加节点 */ public boolean add(E e) { linkLast(e); return true; } 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++; } /** * LinkedList add(index, e) * 1.从头/尾遍历到index * 2.互相添加节点 */ public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } 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++; }
remove
/** * ArrayList remove(index) * 1.index+1之后的元素复制到index之后 * 2.elementData[--size] = null */ public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; } /** * ArrayList remove(Object) * 1.遍历数组找到Object * 2.index+1之后的元素复制到index之后 * 3.elementData[--size] = null */ public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } /** * LinkedList remove(index) * 1.从头/尾遍历到index * 2.将index的前后节点相关联 */ public E remove(int index) { checkElementIndex(index); return unlink(node(index)); } E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) { first = next; } else { prev.next = next; x.prev = null; } if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; } /** * LinkedList remove(Object) * 1.从头/尾遍历到object * 2.将object的前后节点相关联 */ public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; }
ArrayList与Vector
实现原理一样
主要区别:
①线程安全:Vector增删改查的方法都有synchronized,线程安全,但性能较ArrayList差
②扩容:ArrayList每次扩1.5倍(int newCapacity = oldCapacity + (oldCapacity >> 1))
Vector默认扩成原来的2倍(int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity))
参考资料:
ArrayList vs LinkedList vs Vector 区别中进行了实际的性能测试
Java 集合系列08之 List总结(LinkedList, ArrayList等使用场景和性能分析)
技术在于学习 在于实践 在于总结 在于分享