一、Vector与ArrayList 的理解

https://www.cnblogs.com/dengrongzhang/p/9371551.html
https://www.cnblogs.com/rnmb/p/6553711.html

  • Vector是线程安全的集合类,ArrayList并不是线程安全的类。Vector类对集合的元素操作时都加了synchronized,保证线程安全。 我感觉这是最大的不同之处

    Vector:

     public static void main(String[] args) {
    		 Vector<String> v = new Vector<String>();
    		 v.add("test");
    	}
    
     /**
         * Appends the specified element to the end of this Vector.
         *
         * @param e element to be appended to this Vector
         * @return {@code true} (as specified by {@link Collection#add})
         * @since 1.2
         * 加锁  效率低了
         */
        public synchronized boolean add(E e) {
            modCount++;
            ensureCapacityHelper(elementCount + 1);
            elementData[elementCount++] = e;
            return true;
        }
    

    ArrayList:

    public static void main(String[] args) {
    		ArrayList<String> al = new ArrayList<String>();
    		al.add("test");
    	}
    
     /**
         * Appends the specified element to the end of this list.
         *
         * @param e element to be appended to this list
         * @return <tt>true</tt> (as specified by {@link Collection#add})
         * 没有加锁 线程不安全
         */
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    
  • Vector与ArrayList本质上都是一个Object[] 数组,ArrayList提供了size属性,Vector提供了elementCount属性,他们的作用是记录集合内有效元素的个数。与我们平常调用的arrayList.size()和vector.size()一样返回的集合内有效元素的个数。
    Vector与ArrayList的扩容并不一样,Vector默认扩容是增长一倍的容量,Arraylist是增长50%的容量。
    技术问答-13
    技术问答-13
    技术问答-13
    技术问答-13

  • Vector与ArrayList的remove,add(index,obj)方法都会导致内部数组进行数据拷贝的操作,这样在大数据量时,可能会影响效率。
    技术问答-13

  • Vector与ArrayList的add(obj)方法,如果新增的有效元素个数超过数组本身的长度,都会导致数组进行扩容。

  • 技术问答-13

  • ArrayList

/**
 * 初始化大小
 */
private static final int DEFAULT_CAPACITY = 10;
//底层是数组
transient Object[] elementData;  
//无参构造函数  private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//带参数构造 这个参数是一个集合 相当于初始化集合
public ArrayList(Collection<? extends E> c) {
//带参构造  参数是int类型 初始化数组的大小 覆盖默认值
public ArrayList(int initialCapacity) {

//数组的长度  int类型 默认是0 
 private int size;
 private void grow(int minCapacity) {
        // 旧数组容量
        int oldCapacity = elementData.length;
        // 新数组容量=旧数组容量+旧数组容量*0.5 (>>1 相当于除以2 速度快)
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //如果新容量 小于 最小容量限度(size+1) 新容量设置为minCapacity 
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //如果比最大容量int MAX_ARRAY_SIZE  = Integer.MAX_VALUE - 8 
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //复制到新数组中
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
//
 private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // 溢出了 报错 minCapacity 为什么可能小于0 ? 因为Integer.MAX_VALUE+1 会变成负数 
            throw new OutOfMemoryError();
        //返回Integer.MAX_VALUE  或 MAX_ARRAY_SIZE
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }
//删除
public E remove(int index) {
		//检查下标合法性 
        rangeCheck(index);
		//修改次数 这个是为了在同时修改或者迭代器next的时候   报错 ConcurrentModificationException
        modCount++;
        //获取旧值 需要返回 
        E oldValue = elementData(index);
		//需要移动的数据的总数 
		//                数据源    开始复制地址    目标      目标存放开始地址  复制的长度 
		//arraycopy(Object src,int srcPos,Object dest,int destPos,int length)   
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        //设置为null  让gc垃圾回去取回收东西~~         
        elementData[--size] = null; // clear to let GC do its work
		//返回旧值 
        return oldValue;
}
//检查下标是否越界
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//越界打印信息 这就是我们常常看到的 输出的越界报错信息 神奇
private String outOfBoundsMsg(int index) {
    return "Index: "+index+", Size: "+size;
}
//修改指定下标的值
 public E set(int index, E element) {
 		//检查下标合法性
        rangeCheck(index);
		//获取旧值
        E oldValue = elementData(index);
        //设置新值
        elementData[index] = element;
        //返回旧值
        return oldValue;
    }
  //指定位置添加元素 
  public void add(int index, E element) {
  		//下标合法性
        rangeCheckForAdd(index);
		//检查数组长度是否需要增容  modCount加1
        ensureCapacityInternal(size + 1); 
        //复制数组 把index这个地方留下来
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        //修改指定下标位置的数据
        elementData[index] = element;
        size++;
    }

其实简单看这些源码不是很难 但是想要再深入了解 那肯定就会有点儿难度

相关文章:

  • 2021-06-07
  • 2021-06-12
  • 2021-10-27
  • 2022-03-03
  • 2021-11-25
  • 2022-12-23
  • 2021-07-28
  • 2022-02-18
猜你喜欢
  • 2021-07-20
  • 2021-04-19
  • 2021-10-03
  • 2022-12-23
  • 2021-10-29
  • 2021-04-10
  • 2021-10-17
相关资源
相似解决方案