集合源码分析(一)ArrayList集合

1、ArrayList 概述

ArrayList 是 Collection 单例集合体系中使用率最多的一个集合。是 List 的第一个实现类,全面替代了 Vector 。底层是数组结构的.
特点:
    有序、有索引、可以重复。

基本使用:
    ArrayList<Integer> al = new ArrayList<>();
        al.add(1);
        al.add(2);
        al.add(3);

2、ArrayList 的四种遍历方式:

2.1、增强for

   //i只是其中的一个变量,更改i的值,不会更改集合中的数据

  for (Integer i : al) {
       System.out.println(i);
  }

2.2、迭代器

   //在迭代的时候不能利用集合的方法改变集合的长度。会报并发修改异常

Iterator<Integer> it = al.iterator();
while(it.hasNext()){
      Integer next = it.next();
      System.out.println(next);
}


2.3、普通for

//在删除数据的时候,要i--。否则会导致相邻的两个数不能删除

for (int i = 0; i < al.size(); i++) {
    Integer ii = al.get(i);
    System.out.println(ii);
}

2.4、转数组

Object[] array = al.toArray(); //toArray()没有传递参数,所以是object类型的
for (Object o : array) {
    System.out.println(o);
}

Integer[] array = al.toArray(new Integer[0]);//传递一个T类型的数组,那么返回值就是T类型的。
                                    //此处数组长度与集合长度比,谁长听谁的,不足null补齐。
                                    //所以可以写0或者是集合的size
for (Integer i : array) {                    
    System.out.println(i);
}

3、方法解析:

3.1、无参构造

ArrayList<Integer> al = new ArrayList<>();
public ArrayList() {
    super();
this.elementData = EMPTY_ELEMENTDATA;
//elementData 是ArrayList底层实际存值的数组
//EMPTY_ELEMENTDATA 是一个object类型的空数组
//创建对象的时候ArrayList就是一个空数组
}

3.2、add():

void add(int index, E element):将指定的元素插入此列表中的指定位置。
 //如果集合中最大索引是3,那么调用此方法,可以在4索引插入元素。但是超过4索引就报错了。

boolean add(Object e): 向集合中添加元素。

//方法源码分析:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);//重新计算长度,并让modCount++
				//modCount是并发修改异常中的关键,下面会解释
    elementData[size++] = e;//每次往数组的末尾存。保证了存取有序
    return true;	//因为ArrayList可重复所以每次都是true。跟HashSet相对
} 

//-----------------------	
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
    minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//默认大小跟实际大小比较
}//保证了ArrayList只要刚开始添加就有一个默认10大小的容量,因为DEFAULT_CAPACITY = 10;
							ensureExplicitCapacity(minCapacity);
}

//------------------------
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//modCount是并发修改异常中的关键,下面会解释
    if (minCapacity - elementData.length > 0)//比较长度
	grow(minCapacity);
}

//------------------------
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;//旧容量
    int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量 = 旧容量 + 旧容量/2
    if (newCapacity - minCapacity < 0)
	newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
	newCapacity = hugeCapacity(minCapacity);
	elementData = Arrays.copyOf(elementData, newCapacity);//数组的拷贝//底层调用System.arraycopy拷贝
}

    综上所述:ArrayList 底层是一个长度为0的数组。在刚添加一个元素后,变成默认大小10。
              只要是存满了。那么就把原来的长度*1.5(也就是扩容原先的1.5倍大小。)
              再创建了一个新的数组,新的数组的长度为原来的1.5倍
              利用 System.arraycopy 的方法将原数组的内容拷贝到新的数组中去。

3.3、clear():

void clear():清空集合中所有元素。
 //方法源码分析                

for (int i = 0; i < size; i++)  //遍历集合
    elementData[i] = null;   //得到每一个元素,把每一个元素变成null
    size = 0;                //将长度变为0

3.4、contain():

boolean contains(Object o):判断集合中是否包含某个元素。
//方法源码分析
        

扫描二维码关注公众号,回复: 3227237 查看本文章
public boolean contains(Object o) {
     return indexOf(o) >= 0;//调用indexOf看参数在集合中是多少索引。
                            //如果索引为正数,那么集合中就包含参数
}

//------------------------
public int indexOf(Object o) {
    if (o == null) {        //判断参数是否为null
    for (int i = 0; i < size; i++)//遍历
    if (elementData[i]==null)//判断遍历到的是否为null
        return i;            //如果存在就直接return
    } else {
        for (int i = 0; i < size; i++)    //遍历
            if (o.equals(elementData[i])) //利用equals进行判断
               return i;                  //如果存在就直接return
             }
        return -1;//如果不存在就return-1
}

                    
    综上所述:"方法底层是依赖 equals" 方法来判断是否是否与集合内部某一个元素相同。
              如果我们没有重写equals。那么用的是object里面的equals。此时判断的是地址值。
              当遇到一个匹配的直接return,所以当重复时候,只能返回第一个。

3.5、isEmpty():

boolean isEmpty():判断集合中的元素是否为空

//方法源码分析                         

 public boolean isEmpty() {
       return size == 0;//就是判断长度是否为0
 }

3.6、remove(Object o):

boolean remove(Object o):根据元素的内容来删除某个元素

后续。。。。

猜你喜欢

转载自blog.csdn.net/MyronCham/article/details/82626601