简单了解ArrayList源码

ArrayList
1.创建ArrayList list1 = new ArrayList();
默认创建了一个空的数组

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 }

2.执行 list1.add(1);

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 确保数组容量,如果是空数组,那么就设置默认长度或是设置设置为数据的长度。如果非空数组,长度不够就进行扩容。
        elementData[size++] = e; //新添加的对象进行赋值
        return true;
}
 private static final int DEFAULT_CAPACITY = 10; //默认长度为10

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

    ensureExplicitCapacity(minCapacity);//进行分配数组长度
 }  

  private void ensureExplicitCapacity(int minCapacity) {
    modCount++;  
    if (minCapacity - elementData.length > 0) //需要的长度大于当前数组的长度,就进行扩容
        grow(minCapacity);
    }

private void grow(int minCapacity) { 
    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);//进行数组的复制,创建一个新数组将旧数组的值复制到新数组中。
}

3.执行list1.addAll(list2);

public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();  //上来马上将类型转化成数组,然后其他的步骤跟add()基本相同
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}

4.list1.add(index,element) 指定的位置上,添加一个元素,这时候集合的长度会添加

public void add(int index, E element) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    //下面进行数组的指定位置的复制,将elementData中的index位置开始的数据复制到当前数据的
       index+1位置开始逐条复制。并最后将element赋值到index位置上
    System.arraycopy(elementData, index, elementData, index + 1,
            size - index);    
    elementData[index] = element;
    size++;
}

5. list1.set(2,10); 这个方法是将索引为2的位置上的数据进行赋值,并返回被替换的数据。

     public E set(int index, E element) {
        if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

    E oldValue = (E) elementData[index];
    elementData[index] = element;
    return oldValue;
}

6. list1.remove((Integer) 11);

//无非是进行遍历,然后删除数据
public boolean remove(Object o) {
    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++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
//还是将数组中从index+1处的数据开始复制到索引在index处。
        System.arraycopy(elementData, index + 1, elementData, index,
                numMoved); 
    elementData[--size] = null; //将最后一条数据清空
}

7.list1.indexOf(1) //进行遍历,找到元素,并返回索引

public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i] == null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;

8.list1.contains(-1)

public boolean contains(Object o) {
    return indexOf(o) >= 0;  //如果不为-1,证明找到数据,返回true
}

9.list1.remove(0)和直接remove对象的方法的区别,就只不用先找到数据的索引。

public E remove(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(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; // clear to let GC do its work

    return oldValue;
}

10.list1.get(0)

public E get(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
//直接取数组中的数据
    return (E) elementData[index];

11.list1.toArray(); 其实就是数组的复制

  public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}
  public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}

   public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
  1. 执行代码Iterator iterator = list1.iterator();

        while (iterator.hasNext()){
        Log.e("TAG", "iterator==="+iterator.next().toString());
        iterator.remove();
    }
    在ArrayList中发现源码,iteraor就是一个对象,里面封装了索引。
    private class Itr implements Iterator<E> {
    
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;
    
    public boolean hasNext() {
        return cursor < limit;   //判断当前索引是否小于集合长度
    }
    
    @SuppressWarnings("unchecked")
    public E next() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        int i = cursor;
        if (i >= limit)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];//在这取出数组中的数据,并且为lastRet赋值
    }
    
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    
        try {
            ArrayList.this.remove(lastRet);  //根据在next()中的被赋值的lastRet,调用ArrayList中的根据索引删除的remove()方法,进行删除。因此如果调用remove() 必须先调用next()
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
            limit--;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
    
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
    }   
    

13.List integers = list1.subList(1, 3);

    for(Integer i:integers) {
        Log.e("TAG", "integers==="+i);
    }

 public List<E> subList(int fromIndex, int toIndex) {
    //检查是否越界
    subListRangeCheck(fromIndex, toIndex, size);
     //竟然创建了一个新的对象SubList,这个SubList相当于一个和ArrayList相同的类,里面有和ArrayList相同的方法  
   return new SubList(this, 0, fromIndex, toIndex);
}

//虽然我用了增强for循环,但实质还是调用了get()方法,但是发现,和ArrayList的区别就是,增加了偏移量,仍然维护了由于的数组
这里写图片描述

猜你喜欢

转载自blog.csdn.net/yuezheyue123/article/details/81066261