ArrayList源码理解

构造方法:

     这个类中有一个Object[]的对象来存储数据,代码是:

this.elementData = new Object[initialCapacity];//存储对象的数组
 

    initialCapacity默认是10,这个elementData定义的时候用transient定义,不知道什么意思。size为集合的长度int。默认没有给值,所以是0。
    构造方法:

public ArrayList(int initialCapacity) {
        this.elementData = new Object[initialCapacity];
}

    构造方法:

public ArrayList() {
        this(10);
}
 

    在构造方法中

public ArrayList(Collection<? extends E> c) {
          //返回一个Object[]的副本对象(大部分是这样),长度会是内部变量的长度size,而不是这个Object[]的长度
            elementData = c.toArray();
            size = elementData.length;
            //这里验证内部的值是否是Object[],然后依情况转成Object类型
            if (elementData.getClass() != Object[].class)
                 //这里复制出来的Onject[]值所占空间为size,内部变量的数目也是size
                elementData = Arrays.copyOf(elementData, size, Object[].class);
}

      在这个构造方法中会将c中的值转为Object[]类型,在c.toArray()中,一般会传出一个对象的副本,即利用copy传出elementData的数据。所以这里很有可能是复制了两次数据。

add方法

     返回的是否添加成功。注意,这里面竟然可以添加null值。

public boolean add(E e) {
    //增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
    ensureCapacity(size + 1); 
    //复制后size+1
    elementData[size++] = e;
    return true;
 }

    类中的E泛型 不过都会当成Object处理??
    上面的第一句代码:

public void ensureCapacity(int minCapacity) {
                        //不知道这句是干什么的?????????????????????
                        modCount++;
                        //获取当前数组长度,而并不是内部拥有的变量size
                        int oldCapacity = elementData.length;
                        //如果总空间不够的话
                        if (minCapacity > oldCapacity) {
                               
                            Object oldData[] = elementData;
                            //开辟1.5倍+1的空间
                            int newCapacity = (oldCapacity * 3)/2 + 1;
                            //如果依然不够的话,直接开辟minCapacity的空间
                        if (newCapacity < minCapacity)
                                        newCapacity = minCapacity;
                                //将数据复制到新的数组中
                        elementData = Arrays.copyOf(elementData, newCapacity);
         }
} 

      add(int index, E element) 将指定的元素插入此列表中的指定位置。

public void add(int index, E element) {
           //这个就不说了,越界
            if (index > size || index < 0)
                   throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
          //容量保证
          ensureCapacity(size+1); 
         //复制index后size-index长度的值到index+1的位置上,就是将index后面的内容向后移动一位,把index这个位置空出来
         System.arraycopy(elementData, index, elementData, index + 1,size - index);
        //赋值
        elementData[index] = element;
        //大小+1
        size++;
}

 

public boolean addAll(Collection<? extends E> c) {
		Object[] a = c.toArray();
		//a.length 相当于复制过来c的size。这里也是数组所占空间
 		int numNew = a.length;
		ensureCapacity(size + numNew); 
		//将加入的a复制到size之后,注意这里都是数组的位置,
		System.arraycopy(a, 0, elementData, size, numNew);
		//更新size
		size += numNew;
		//这个很有特色,按照添加的长度来判断是否成功。很危险
		return numNew != 0;
}
 
public boolean addAll(int index, Collection<? extends E> c) {
		if (index > size || index < 0)
		    throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
		Object[] a = c.toArray();
		int numNew = a.length;
		ensureCapacity(size + numNew); 
		int numMoved = size - index;
		//这里是判断是否需要系统,如果index 和size一样大的话就复制移动了。
		if (numMoved > 0)
		    System.arraycopy(elementData, index, elementData, index + numNew,numMoved);
		System.arraycopy(a, 0, elementData, index, numNew);
		size += numNew;
		return numNew != 0;
}	

 

get方法

 

public E get(int index) {
	//范围检查
	RangeCheck(index);	
	//竟然会强转,不过想想也很正常。
	return (E) elementData[index];
}			
//只是做了一个越界检查
private void RangeCheck(int index) {
	if (index >= size)
	    throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
}		

 

size方法

 

public int size() {
        //直接返回size的值。
	return size;
}	

 

clear方法

public void clear() {
	//这里又不知道在干什么
	modCount++;
	//看来数组的空间不会改变,内部的变量都清空了。
	for (int i = 0; i < size; i++)
			//所有的值赋了空值。
	    elementData[i] = null;
	size = 0;
}		

remove方法        

    返回删除对象

public E remove(int index) {
 	//判断是否越界
		RangeCheck(index);
		  //这里又不知道在干什么
		modCount++;
		//强转
		E oldValue = (E) elementData[index];
		//看是否需要复制移动
		int numMoved = size - index - 1;
		if (numMoved > 0)
		    System.arraycopy(elementData, index+1, elementData, index,numMoved);
		elementData[--size] = null; 
		//返回
		return oldValue;
}		

 

    返回是否删除成功

public boolean remove(Object o) {
 //第一步直接把对象强转为Object类型了。
		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++)
	   	 			//注意这里判断的删除只是equals相同就行,这个地方很有奇异,
						if (o.equals(elementData[index])) {
						    fastRemove(index);
						    //只会删除碰到的第一条相同对象
						    return true;
						}
       	}
   //没找到会返回false。
	return false;
}
 

 

   快速删除

private void fastRemove(int index) {
 	//又是这个神秘的变量
  modCount++;
  //和上面的删除是一个人写的,一样。
  int numMoved = size - index - 1;
  if (numMoved > 0)
      System.arraycopy(elementData, index+1, elementData, index, numMoved);
  //size-1
  elementData[--size] = null;
}

 

   ArrayList里面的removeAll是调用的下面class的方法。

   AbstractCollection.class

 public boolean removeAll(Collection<?> c) {
			boolean modified = false;
			Iterator<?> e = iterator();
			while (e.hasNext()) {
					//包含的方法下面会看到。
			    if (c.contains(e.next())) {
				e.remove();
				//这里是删除所有的
				modified = true;
			    }
			}
			return modified;
  }

 public boolean retainAll(Collection<?> c) {
			boolean modified = false;
			Iterator<E> e = iterator();
			while (e.hasNext()) {
			    if (!c.contains(e.next())) {
			 //   不包含的关系,就是几乎会删除掉原对象中所有的值
				e.remove();
				modified = true;
			    }
			}
			return modified;
  }

 

indexOf方法     

 

public int indexOf(Object o) {
	if (o == null) {
	    for (int i = 0; i < size; i++)
	    //在size之前找到空,会返回,超过size后没用
		if (elementData[i]==null)
		    return i;
	} else {
	//依然只是比较equals方法。
	    for (int i = 0; i < size; i++)
		if (o.equals(elementData[i]))
			//只返回查找的第一个。
		    return i;
	}
	//找不到返回 int -1
	return -1;
}
 

 

lastIndexOf方法

    lastIndexOf(Object o)
    返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
    和index一样,只是这个循环从最后一个开始,向前循环。所以查找的是最后一个。

toArray方法

 

public Object[] toArray() {
	//返回一个数组,数组空间和变量同样大小的。
	return Arrays.copyOf(elementData, size);
}

    未定义泛型的时候Object[] 不能强转成 E[] ,

trimToSize方法

    将此 ArrayList 实例的容量调整为列表的当前大小

public void trimToSize() {
		//未知
		modCount++;
		int oldCapacity = elementData.length;
		if (size < oldCapacity) {
	            elementData = Arrays.copyOf(elementData, size);
		}
}

 

set方法

     E set(int index,E element)
     就是将对应未知的变量换成新的,将旧的值返回,当然先是对越界做过滤。

isEmpty方法

 

isEmpty() 
 	public boolean isEmpty() {
	return size == 0;
}

    代码更容易懂。

contains方法

    如果此列表中包含指定的元素,则返回 true。

public boolean contains(Object o) {
	return indexOf(o) >= 0;
}

public boolean containsAll(Collection<?> c) {
	Iterator<?> e = c.iterator();
	while (e.hasNext())
  	if (!contains(e.next()))
			return false;
		return true;
} 

   这里是不讲究顺序,只要c中的变量都有就行。例如:a={1,3,2,4},b={1,3,3} 这里,a包含b。

               

clone方法

     克隆被覆写

public Object clone() {
		try {
		    ArrayList<E> v = (ArrayList<E>) super.clone();
		    v.elementData = Arrays.copyOf(elementData, size);
		    v.modCount = 0;
		    return v;
		} catch (CloneNotSupportedException e) {
		    // this shouldn't happen, since we are Cloneable
		    throw new InternalError();
		}
}	
 

       
  好了ArrayList 就算看完了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值