赞
踩
今天和朋友聊天,谈到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提供的双向链表,进行节点插入删除要高效很多,但是随即访问要比动态数组慢,不需要像上面两种调整容量,线程也是不安全的。
因此,在选用哪个集合类存储时要根据使用场景进行针对性的选择。
构造方法:
- /**
- * Constructs an empty list with the specified initial capacity.
- *
- * @param initialCapacity the initial capacity of the list
- * @throws IllegalArgumentException if the specified initial capacity
- * is negative
- */
- public ArrayList(int initialCapacity) {
- if (initialCapacity > 0) {
- this.elementData = new Object[initialCapacity];
- } else if (initialCapacity == 0) {
- this.elementData = EMPTY_ELEMENTDATA;
- } else {
- throw new IllegalArgumentException("Illegal Capacity: "+
- initialCapacity);
- }
- }
-
- /**
- * Constructs an empty list with an initial capacity of ten.
- */
- public ArrayList() {
- this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
- }
-
- /**
- * Constructs a list containing the elements of the specified
- * collection, in the order they are returned by the collection's
- * iterator.
- *
- * @param c the collection whose elements are to be placed into this list
- * @throws NullPointerException if the specified collection is null
- */
- public ArrayList(Collection<? extends E> c) {
- elementData = c.toArray();
- if ((size = elementData.length) != 0) {
- // c.toArray might (incorrectly) not return Object[] (see 6260652)
- if (elementData.getClass() != Object[].class)
- elementData = Arrays.copyOf(elementData, size, Object[].class);
- } else {
- // replace with empty array.
- this.elementData = EMPTY_ELEMENTDATA;
- }
- }
可以看到,调用无参构造函数,有初始化容量的话,创建一个初始化容量大小的数组,没有到话创建一个空数组,在调用add 方法时会进行真正初始化.使用默认的初始化容量10.
- public boolean add(E e) {
- ensureCapacityInternal(size + 1); // Increments modCount!!
- elementData[size++] = e;
- return true;
- }
-
-
-
- private void ensureCapacityInternal(int minCapacity) {
- if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
- minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
- }
-
- ensureExplicitCapacity(minCapacity);
- }
-
-
- private void ensureExplicitCapacity(int minCapacity) {
- // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的
- modCount++;
- // 防止溢出代码:确保指定的最小容量 > 数组缓冲区当前的长度
- // overflow-conscious code
- if (minCapacity - elementData.length > 0)
- grow(minCapacity);
- }
其中ensureCapacityInternal()方法当第一次数组为空时,将minCapacity 设置为10,后续比较时,当添加的元素小于10个的时候不扩容,当添加第11 个时,此时ensureCapacityInternal(int minCapacity =11),比较后11- 10>0,进行扩容。
- 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);
- }
进行右移后时间上是*0.5。
先看下构造方法:
- 无参构造
- /**
- * Constructs an empty vector so that its internal data array
- * has size {@code 10} and its standard capacity increment is
- * zero.
- */
- public Vector() {
- this(10);
- }
- public Vector(int initialCapacity) {
- this(initialCapacity, 0);
- }
-
- public Vector(int initialCapacity, int capacityIncrement) {
- super();
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal Capacity: "+
- initialCapacity);
- this.elementData = new Object[initialCapacity];
- this.capacityIncrement = capacityIncrement;
- }
和ArrayList 类似,默认Vector 也会创建一个初始容量为10的数组,其容量增量为0;
add()方法:
可以看到,add方法上已经使用了synchronized .
- public synchronized void addElement(E obj) {
- modCount++;
- ensureCapacityHelper(elementCount + 1);
- elementData[elementCount++] = obj;
- }
-
-
- private void ensureCapacityHelper(int minCapacity) {
- // overflow-conscious code
- if (minCapacity - elementData.length > 0)
- grow(minCapacity);
- }
-
- private void grow(int minCapacity) {
- // overflow-conscious code
- int oldCapacity = elementData.length;
- int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
- capacityIncrement : oldCapacity);
- if (newCapacity - minCapacity < 0)
- newCapacity = minCapacity;
- if (newCapacity - MAX_ARRAY_SIZE > 0)
- newCapacity = hugeCapacity(minCapacity);
- elementData = Arrays.copyOf(elementData, newCapacity);
- }
可以看到,Vector 在扩容的时候,先判断增量因子是否大于0 ,大于0的话在原来的基础上+capacityIncrement,否则的话就是加上oldCapacity.
关于其他方法,就不一一介绍了,最好是通过Demo+debug的方式一步一步跟踪,方得始终,就酱。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。