当前位置:   article > 正文

java 集合类之ArrayList、LinkedList 和Vector_arraylist和vector都是java的集合类

arraylist和vector都是java的集合类

今天和朋友聊天,谈到java中的集合类问题,对于其中的用法和特点有些遗忘的地方,再次梳理和记录下。首先是常用的ArrayList 和Vector。(java 8),狭义(不包含Map)集合类UML 图:

联系和区别:

ArrayList  和Vector 都继承了AbstractList,而和LinkedList 同时实现了List 接口,因此具有List的一些特点,比如底层都是用数组来存储的。也因此两者有数组有关的优缺点比如根据下标进行访问,查询速度快,时间复杂度O(1),缺点是添加和删除涉及到元素的复制、移动问题,效率相对低的缺点。提供了迭代器遍历的功能

1、ArrayList是线程不安全的类;而Vector是线程安全的集合类,源码中Vector类对集合的元素操作时都加了synchronized,保证线程安全。也因此在不考虑线程安全的前提下,相比Vector,效率上ArrayList 相对高效写(大家都这么说)

2、动态扩展方面:Vector默认扩容是先判断整张因子是否大于0,(默认为0),若大于0,则将数组大小扩大为size+capacityIncrement,否则增长一倍的容量,Arraylist是增长50%的容量。

3、LinkedList 是java提供的双向链表,进行节点插入删除要高效很多,但是随即访问要比动态数组慢,不需要像上面两种调整容量,线程也是不安全的。

因此,在选用哪个集合类存储时要根据使用场景进行针对性的选择。

源码分析:

首先是ArrayList :

构造方法:

  1. /**
  2. * Constructs an empty list with the specified initial capacity.
  3. *
  4. * @param initialCapacity the initial capacity of the list
  5. * @throws IllegalArgumentException if the specified initial capacity
  6. * is negative
  7. */
  8. public ArrayList(int initialCapacity) {
  9. if (initialCapacity > 0) {
  10. this.elementData = new Object[initialCapacity];
  11. } else if (initialCapacity == 0) {
  12. this.elementData = EMPTY_ELEMENTDATA;
  13. } else {
  14. throw new IllegalArgumentException("Illegal Capacity: "+
  15. initialCapacity);
  16. }
  17. }
  18. /**
  19. * Constructs an empty list with an initial capacity of ten.
  20. */
  21. public ArrayList() {
  22. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  23. }
  24. /**
  25. * Constructs a list containing the elements of the specified
  26. * collection, in the order they are returned by the collection's
  27. * iterator.
  28. *
  29. * @param c the collection whose elements are to be placed into this list
  30. * @throws NullPointerException if the specified collection is null
  31. */
  32. public ArrayList(Collection<? extends E> c) {
  33. elementData = c.toArray();
  34. if ((size = elementData.length) != 0) {
  35. // c.toArray might (incorrectly) not return Object[] (see 6260652)
  36. if (elementData.getClass() != Object[].class)
  37. elementData = Arrays.copyOf(elementData, size, Object[].class);
  38. } else {
  39. // replace with empty array.
  40. this.elementData = EMPTY_ELEMENTDATA;
  41. }
  42. }

可以看到,调用无参构造函数,有初始化容量的话,创建一个初始化容量大小的数组,没有到话创建一个空数组,在调用add 方法时会进行真正初始化.使用默认的初始化容量10.

  1. public boolean add(E e) {
  2. ensureCapacityInternal(size + 1); // Increments modCount!!
  3. elementData[size++] = e;
  4. return true;
  5. }
  6. private void ensureCapacityInternal(int minCapacity) {
  7. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  8. minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  9. }
  10. ensureExplicitCapacity(minCapacity);
  11. }
  12. private void ensureExplicitCapacity(int minCapacity) {
  13. // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的
  14. modCount++;
  15. // 防止溢出代码:确保指定的最小容量 > 数组缓冲区当前的长度
  16. // overflow-conscious code
  17. if (minCapacity - elementData.length > 0)
  18. grow(minCapacity);
  19. }

其中ensureCapacityInternal()方法当第一次数组为空时,将minCapacity 设置为10,后续比较时,当添加的元素小于10个的时候不扩容,当添加第11 个时,此时ensureCapacityInternal(int minCapacity =11),比较后11- 10>0,进行扩容。

  1. private void grow(int minCapacity) {
  2. // overflow-conscious code
  3. int oldCapacity = elementData.length;
  4. // 运算符 >> 是带符号右移
  5. int newCapacity = oldCapacity + (oldCapacity >> 1);
  6. if (newCapacity - minCapacity < 0)
  7. newCapacity = minCapacity;
  8. if (newCapacity - MAX_ARRAY_SIZE > 0)
  9. newCapacity = hugeCapacity(minCapacity);
  10. // minCapacity is usually close to size, so this is a win:
  11. elementData = Arrays.copyOf(elementData, newCapacity);
  12. }

进行右移后时间上是*0.5。

Vector:

先看下构造方法:

  1. 无参构造
  2. /**
  3. * Constructs an empty vector so that its internal data array
  4. * has size {@code 10} and its standard capacity increment is
  5. * zero.
  6. */
  7. public Vector() {
  8. this(10);
  9. }
  10. public Vector(int initialCapacity) {
  11. this(initialCapacity, 0);
  12. }
  13. public Vector(int initialCapacity, int capacityIncrement) {
  14. super();
  15. if (initialCapacity < 0)
  16. throw new IllegalArgumentException("Illegal Capacity: "+
  17. initialCapacity);
  18. this.elementData = new Object[initialCapacity];
  19. this.capacityIncrement = capacityIncrement;
  20. }

和ArrayList 类似,默认Vector 也会创建一个初始容量为10的数组,其容量增量为0;

add()方法:

可以看到,add方法上已经使用了synchronized .

  1. public synchronized void addElement(E obj) {
  2. modCount++;
  3. ensureCapacityHelper(elementCount + 1);
  4. elementData[elementCount++] = obj;
  5. }
  6. private void ensureCapacityHelper(int minCapacity) {
  7. // overflow-conscious code
  8. if (minCapacity - elementData.length > 0)
  9. grow(minCapacity);
  10. }
  11. private void grow(int minCapacity) {
  12. // overflow-conscious code
  13. int oldCapacity = elementData.length;
  14. int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
  15. capacityIncrement : oldCapacity);
  16. if (newCapacity - minCapacity < 0)
  17. newCapacity = minCapacity;
  18. if (newCapacity - MAX_ARRAY_SIZE > 0)
  19. newCapacity = hugeCapacity(minCapacity);
  20. elementData = Arrays.copyOf(elementData, newCapacity);
  21. }

可以看到,Vector 在扩容的时候,先判断增量因子是否大于0 ,大于0的话在原来的基础上+capacityIncrement,否则的话就是加上oldCapacity.

关于其他方法,就不一一介绍了,最好是通过Demo+debug的方式一步一步跟踪,方得始终,就酱。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/322073
推荐阅读
相关标签
  

闽ICP备14008679号