当前位置:   article > 正文

ArrayList、Vector和LinkedList的区别及使用场景

arraylist、vector和linkedlist的区别及使用场景

一、前言

ArrayList、Vector和LinkedList都是实现了List接口(允许数据重复)的容器类,它们都能对元素做增删改查的操作。

二、具体介绍

  • ArrayList

ArrayList是基于数组实现的,采用懒加载策略(第一次add时才初始化内部数组,默认初始化大小为10)。它允许对元素的快速随机访问以及在链表尾部进行插入或删除元素操作。但是当随机插入元素时,如果此时数组大小已经不能满足再插入元素时就会进行扩容操作【扩容为原来集合容量的1.5倍】,然后将已插入元素复制到新的存储空间中。如果从中间插入或删除数据势必会导致大量数据的复制,搬移等,这样的话代价会很高。由此看来,ArrayList适合随机访问,而不适合插入和删除。采用异步处理,线程不安全,性能较高

  1. /**
  2. * The array buffer into which the elements of the ArrayList are stored.
  3. * The capacity of the ArrayList is the length of this array buffer. Any
  4. * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
  5. * will be expanded to DEFAULT_CAPACITY when the first element is added.
  6. */
  7. //ArrayList的元素是存储在缓冲数组中的,并且ArrayList的容量就是缓冲数组的长度
  8. //任何一个属性值elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA的ArrayList都会在第一次添加元素的时候扩容为默认容量DEFAULT_CAPACITY
  9. transient Object[] elementData; // non-private to simplify nested class access
  10. /**
  11. * The size of the ArrayList (the number of elements it contains).
  12. *
  13. * @serial
  14. */
  15. //ArrayList的大小(所含元素的个数)
  16. private int size;
  17. /**
  18. * Default initial capacity.
  19. */
  20. //默认的容量
  21. private static final int DEFAULT_CAPACITY = 10;
  22. /**
  23. * Shared empty array instance used for default sized empty instances. We
  24. * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
  25. * first element is added.
  26. */
  27. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  28. /**
  29. * Constructs an empty list with an initial capacity of ten.
  30. */
  31. //构造一个空集合
  32. public ArrayList() {
  33. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  34. }
  35. /**
  36. * Appends the specified element to the end of this list.
  37. *
  38. * @param e element to be appended to this list
  39. * @return <tt>true</tt> (as specified by {@link Collection#add})
  40. */
  41. //向集合尾部添加特定元素
  42. public boolean add(E e) {
  43. ensureCapacityInternal(size + 1); // Increments modCount!!
  44. elementData[size++] = e;
  45. return true;
  46. }
  47. private void ensureCapacityInternal(int minCapacity) {
  48. //第一次插入元素的情况,此时才开始初始化数组,长度为DEFAULT_CAPACITY(10)
  49. //minCapacity=Math.max(10,1)=10;
  50. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  51. minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  52. }
  53. ensureExplicitCapacity(minCapacity);
  54. }
  55. /**
  56. * The number of times this list has been <i>structurally modified</i>.
  57. * Structural modifications are those that change the size of the
  58. * list, or otherwise perturb it in such a fashion that iterations in
  59. * progress may yield incorrect results.
  60. */
  61. //modCount记录的是list的结构被修改的次数
  62. //结构被修改指的是改变了list的大小【添加或者删除元素的时候】
  63. //否则,如果在进行迭代器循环的时候如果修改了modCount的值可能会导致错误的结果
  64. protected transient int modCount = 0;
  65. private void ensureExplicitCapacity(int minCapacity) {
  66. //modCount=0
  67. modCount++;
  68. //modCount=1
  69. // overflow-conscious code
  70. //加上正准备插入的这个元素,此时的总元素个数如果大于了数组elementData的长度才会扩容
  71. //也就是说如果elementData的长度为10,那么只有在准备插入11的元素的时候才会扩容
  72. if (minCapacity - elementData.length > 0)
  73. grow(minCapacity);
  74. }
  75. /**
  76. * Increases the capacity to ensure that it can hold at least the
  77. * number of elements specified by the minimum capacity argument.
  78. *
  79. * @param minCapacity the desired minimum capacity
  80. */
  81. //扩容操作
  82. //每次扩容为原集合容量的1.5倍: newCapacity = oldCapacity + (oldCapacity >> 1)
  83. private void grow(int minCapacity) { //minCapacity=10
  84. // overflow-conscious code
  85. int oldCapacity = elementData.length; //oldCapacity=0
  86. int newCapacity = oldCapacity + (oldCapacity >> 1); //newCapacity=0+(0>>1)=0
  87. if (newCapacity - minCapacity < 0) //0-10=-10
  88. newCapacity = minCapacity; //newCapacity=10
  89. if (newCapacity - MAX_ARRAY_SIZE > 0)
  90. newCapacity = hugeCapacity(minCapacity);
  91. // minCapacity is usually close to size, so this is a win:
  92. elementData = Arrays.copyOf(elementData, newCapacity); //进行数组拷贝,此时的newCapacity=10
  93. }
  • Vector

Vector和ArrayList一样,也是基于数组实现的。在实例化对象时就初始化内部数组(大小为10) ,且Vector支持线程同步,即在多线程的环境下,能保证同一时间只有一个线程能够操控Vector,保证了数据的一致性【采用synchronized修饰增删改查方法】。但正是由于Vector保证了线程同步(锁的粒度太粗,将当前集合对象锁住,读读都互斥),所以导致了其性能较ArrayList低很多。

  1. /**
  2. * The array buffer into which the components of the vector are
  3. * stored. The capacity of the vector is the length of this array buffer,
  4. * and is at least large enough to contain all the vector's elements.
  5. *
  6. * <p>Any array elements following the last element in the Vector are null.
  7. *
  8. * @serial
  9. */
  10. //vector的元素也是存放在数组中的
  11. protected Object[] elementData;
  12. /**
  13. * Constructs an empty vector so that its internal data array
  14. * has size {@code 10} and its standard capacity increment is
  15. * zero.
  16. */
  17. //首先初始化一个容量为10的数组
  18. public Vector() {
  19. this(10);
  20. }
  21. /**
  22. * Appends the specified element to the end of this Vector.
  23. *
  24. * @param e element to be appended to this Vector
  25. * @return {@code true} (as specified by {@link Collection#add})
  26. * @since 1.2
  27. */
  28. //synchronized修饰方法,向集合尾部添加元素
  29. public synchronized boolean add(E e) {
  30. modCount++;
  31. ensureCapacityHelper(elementCount + 1);
  32. elementData[elementCount++] = e;
  33. return true;
  34. }
  35. /**
  36. * This implements the unsynchronized semantics of ensureCapacity.
  37. * Synchronized methods in this class can internally call this
  38. * method for ensuring capacity without incurring the cost of an
  39. * extra synchronization.
  40. *
  41. * @see #ensureCapacity(int)
  42. */
  43. //加上正准备插入的这个元素,此时的总元素个数如果大于了数组elementData的长度才会扩容
  44. //也就是说如果elementData的长度为10,那么只有在准备插入11的元素的时候才会扩容
  45. private void ensureCapacityHelper(int minCapacity) {
  46. // overflow-conscious code
  47. if (minCapacity - elementData.length > 0)
  48. grow(minCapacity);
  49. }
  50. //扩容操作
  51. //扩容为原集合容量的2倍
  52. private void grow(int minCapacity) {
  53. // overflow-conscious code
  54. int oldCapacity = elementData.length;
  55. int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
  56. capacityIncrement : oldCapacity);
  57. if (newCapacity - minCapacity < 0)
  58. newCapacity = minCapacity;
  59. if (newCapacity - MAX_ARRAY_SIZE > 0)
  60. newCapacity = hugeCapacity(minCapacity);
  61. elementData = Arrays.copyOf(elementData, newCapacity); //进行数组拷贝,此时的newCapacity=10
  62. }
  63. /**
  64. * Replaces the element at the specified position in this Vector with the
  65. * specified element.
  66. *
  67. * @param index index of the element to replace
  68. * @param element element to be stored at the specified position
  69. * @return the element previously at the specified position
  70. * @throws ArrayIndexOutOfBoundsException if the index is out of range
  71. * ({@code index < 0 || index >= size()})
  72. * @since 1.2
  73. */
  74. public synchronized E set(int index, E element) {
  75. if (index >= elementCount)
  76. throw new ArrayIndexOutOfBoundsException(index);
  77. E oldValue = elementData(index);
  78. elementData[index] = element;
  79. return oldValue;
  80. }
  81. /**
  82. * Returns the element at the specified position in this Vector.
  83. *
  84. * @param index index of the element to return
  85. * @return object at the specified index
  86. * @throws ArrayIndexOutOfBoundsException if the index is out of range
  87. * ({@code index < 0 || index >= size()})
  88. * @since 1.2
  89. */
  90. public synchronized E get(int index) {
  91. if (index >= elementCount)
  92. throw new ArrayIndexOutOfBoundsException(index);
  93. return elementData(index);
  94. }
  95. /**
  96. * Removes the element at the specified position in this Vector.
  97. * Shifts any subsequent elements to the left (subtracts one from their
  98. * indices). Returns the element that was removed from the Vector.
  99. *
  100. * @throws ArrayIndexOutOfBoundsException if the index is out of range
  101. * ({@code index < 0 || index >= size()})
  102. * @param index the index of the element to be removed
  103. * @return element that was removed
  104. * @since 1.2
  105. */
  106. public synchronized E remove(int index) {
  107. modCount++;
  108. if (index >= elementCount)
  109. throw new ArrayIndexOutOfBoundsException(index);
  110. E oldValue = elementData(index);
  111. int numMoved = elementCount - index - 1;
  112. if (numMoved > 0)
  113. System.arraycopy(elementData, index+1, elementData, index,
  114. numMoved);
  115. elementData[--elementCount] = null; // Let gc do its work
  116. return oldValue;
  117. }
  • LinkedList

LinkedList是基于双向链表实现的,它支持对数据的随机插入和删除。但是如果要访问元素的话就比较慢了,它必须从头遍历。

  1. /**
  2. * Pointer to first node.
  3. * Invariant: (first == null && last == null) ||
  4. * (first.prev == null && first.item != null)
  5. */
  6. transient Node<E> first;
  7. /**
  8. * Pointer to last node.
  9. * Invariant: (first == null && last == null) ||
  10. * (last.next == null && last.item != null)
  11. */
  12. transient Node<E> last;
  13. /**
  14. * Constructs an empty list.
  15. */
  16. public LinkedList() {
  17. }
  18. private static class Node<E> {
  19. E item;
  20. Node<E> next;
  21. Node<E> prev;
  22. Node(Node<E> prev, E element, Node<E> next) {
  23. this.item = element;
  24. this.next = next;
  25. this.prev = prev;
  26. }
  27. }

三、区别

1、从初始化、扩容、线程安全三方面对比ArrayList与Vector

ArrayList采用懒加载策略(第一次add时才初始化内部数组,默认初始化大小为10)   扩容为原先数组大小的1.5倍。采用异步处理,线程不安全,性能较高       ArrayList在大部分场合(80%,频繁查找、在集合末端插入与删除)都采用ArrayList

Vector在实例化对象时就初始化内部数组(大小为10),capacityIncrement默认为0,扩容为原先数组大小的2倍。采用synchronized修饰增删改查方法,线程安全,性能较低(锁的粒度太粗,将当前集合对象锁住,读读都互斥),即使要用性能安全的集合,也不推荐使用Vector

2.LinkedList采用异步处理,线程不安全  频繁在任意位置的插入与删除考虑使用LinkedList  LinkedList是Queue接口的常用子类

四、使用场景

如果你的程序更多的是进行元素的随机访问或者从集合末端插入或删除元素,建议使用ArrayList;如果更多的是进行随机插入和删除操作,LinkedList会更优。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号