集合-ArrayList源码分析以及自定义ArrayList集合类实现

版权声明:中华人民共和国持有版权 https://blog.csdn.net/Fly_Fly_Zhang/article/details/87865108
ArrayList特点:
  • 重复性:数据可以重复
  • null值:可以有null值存在
  • 有序性:能保证数据插入有序
ArrayList和数组的区别:
  • 初始化大小:ArrayList可以不指定大小,数组必须指定;
  • 存储数据类型:ArrayList只能存储引用类型,数组可以存储引用类型和基本类型;
常用方法介绍:
  • int size(): 集合中存储元素的个数;
  • boolean isEmpty():判断当前元素是否为空,返回值为boolean类型;
  • boolean contains(Object o): 判断当前集合是否包含Object对象;
  • Iterator iterator(): 迭代器,返回iterator实例;
  • Object[ ] toArray (): 将集合转化成数组;
  • < T > T[ ] toArray( T[ ] a): 将集合转化成数组;
  • boolean add(E e): 添加元素;
  • boolean remove(Object o): 删除元素;
  • boolean containsAll ( Collection < ? > c) : 判断入参集合是否属于当前集合;
  • boolean addAll( Collection < ? extends E > c) : 对该集合添加子集合形成新的集合 ;
  • boolean addAll(int index , Collection< ? extends E > c ) : 在指定的位置添加子集合 ;
  • void clean () : 将集合清除掉;
  • boolean equals(Object o): 判断是否相等;
  • E get(int index):通过指定位置来获取元素;
  • int indexOf (Object o): 判断当前元素在集合中的位置(从头查找);
  • int lastIndexOf (Object o):判断当前元素在集合中的位置(从尾部查找);
  • List< E > subList(int fromIndex ,int toIndex) : 找当前集合的子集;
  • removeAll():list1.remove(list2) ; 这句话的意思是:list1集合与list2集合 先 找到 交集,然后 在 list1中删除 交集 ,然后将删除交集后的list1重新赋给list1,list2中的元素不变,然后打印list1,这样就会输出 删除交集后的 list1 。 removeAll删除的是 两个集合的交集 。
  • retainAll(): boolean flag = list1.retainAll(list2) ; list1 和 list2 两个集合 先取 交集 。 然后 将交集 赋给 list1 , 如果 list1集合元素组成发生了变化,那么就返回 true , 否则返回 false 。特殊情况: list1 和 list2 两个集合 完全相同,所以 list1 和list2 的交集 就是他们 本身, 把交集 赋给 list1时 ,list1 没有发生任何的变化,所以返回 false 。综上所述:retainAll()中 只要list1发生变化,就返回 true,不发生变化就返回false 。

源码分析:

继承关系:
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

  • ArrayList继承AbstractList,父类中对部分接口进行实现;
  • 实现了List接口提供的方法;
  • Serializable说明该类能够被序列化 ,能够被克隆、序列化;
ArrayList底层数据结构是链表;
基本属性:
  • 默认容量大小 :
  private static final int  DEFAULT_CAPACITY = 10;
  • 默认数组大小:
private static final Object[] EMPTY_ELEMENTDATA = {};
  • 存储元素的数组:
private transient Object[] elementData;
  • 集合存储元素的个数:
private int size;
构造函数
//有参构造,指定集合初始化大小
public ArrayList(int initialCapacity) {
        super();
        //指定大小不合法,则直接抛出异常
        初始化数组大小
        
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }
   //无参构造
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }
    //有参构造,通过集合来创建新的集合

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
        //集合类型不同,通过copy来将原数组给新数组
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
    
   
增长方式:按照原数组的1.5倍进行扩容;
CRUD方法研究(增删改查):
  • add(E e) : 首先需要进行数组扩容考虑,如果要扩容(size+1 > table.length), 按照1.5倍进行扩容;然后将元素插入数组尾部,并计数 size+1;
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == EMPTY_ELEMENTDATA) { //判断当前数组是否为空
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        //判断当前需要的数组大小与默认数组大小值进行比较,找出最大的
    }

    ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//版本号发生变化

    // 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 + (oldCapacity >> 1);//对原数组长度进行1.5倍扩容
    if (newCapacity - minCapacity < 0)
    //扩容长度小于需要长度,将扩容长度定为需要长度
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 通过copy的的方式实现数组扩容
    elementData = Arrays.copyOf(elementData, newCapacity);
}   
  • remove (Object o): 先找到元素存储位置(null和非null的对象判断相等不同),将后面的元素向前移动 。注意:相同元素存在的情况下,只需要找到从0号开始第一次出现的元素;
public boolean remove(Object o) {
    if (o == null) { //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)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved); //利用copy实现将删除元素后面元素前移的目标
    elementData[--size] = null;//元素个数减一
}  
  • get(int index): 获取元素;
public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}
//输入角标进行合法性检查 
 private void rangeCheck(int index) {
     if (index < 0 || index >= this.size)
         throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 } 
E elementData(int index) {
    return (E) elementData[index];
}      

自定义ArrayList

import java.util.Arrays;
import java.util.Iterator;
import java.util.ListIterator;

/**
 * @Created with IntelliJ IDEA
 * @Description: 自定义ArrayList
 * @Package: collection
 * @author: FLy-Fly-Zhang
 * @Date: 2019/2/15
 * @Time: 20:48
 */
class ArrayList<E> implements Iterable<E>{
    private E[] array;
    private int size;//装填元素对应的角标
    public ArrayList2(){
        this.array=(E[])new Object[10];
        this.size=0;
    }
    
    public boolean isFull(){ // 判断数组是否装满 
        if(size<array.length)
            return true;
        return false;
    }
    private void grow(){ //数组1.5倍扩容
        this.array=Arrays.copyOf(array,size+(size>>1));
    }
    
    public  boolean add(E e){//添加元素
        if(isFull()){
            grow();
        }
        this.array[size++]=e;
        return true;
    }
    private boolean checkRange(int i){ //角标合法性检查
        if(0<i&&i>=size)
            throw new IndexOutOfBoundsException();
        return true;
    }
    public E get(int i){
        checkRange(i);
        return array[i];
       
    }
    public boolean isEmpty(){ //判断数组是否为空
        if(size==0)
            return true;
        return false;
    }
    private void moveLast(int i){ //将i后面的元素向前移一位
        while(i+1<size){
            array[i]=array[i+1];
        }
        size--;
    }
    public boolean remove(Object obj){
        if(isEmpty())
            return false;
        E num=(E)obj;
        for(int i=0;i<size;i++){
            if(array[i].equals(num)){
                moveLast(i);//后面元素向前移动
                return true;
            }
        }
        return false;
    }
    @Override
    public Iterator<E> iterator() { //
         return new Itr(0);
    }
    private  class Itr implements Iterator<E>{
        private int ind;
        protected Itr(int start){
            this.ind=start;
        }
        @Override
        public boolean hasNext() {
            if(ind<size)
                return true;
            return false;

        }
        @Override
        public E next() {
            if(hasNext())
                return get(ind++ );
            throw new IndexOutOfBoundsException();
        }
        @Override
        public void remove() {
            if(hasNext())
                ArrayList2.this.remove(ind);
            throw new IndexOutOfBoundsException();
        }
    }
}
public class ArrayListDemo {

    public static void main(String[] args) {
        ArrayList<Integer> arrayList2 = new ArrayList<Integer>();
        ArrayList<Integer>  arrayList1=new ArrayList<>();
        //添加元素 boolean add(E e)
        arrayList1.add(30);
        arrayList1.add(12);
        arrayList1.add(12);
        arrayList2.add(12);
        arrayList2.add(34);
        arrayList2.add(12);
    }
}

ArrayList迭代器元素详解以及自定义迭代器的实现 请点击

ArrayList求并集,交集,差集 请点击

猜你喜欢

转载自blog.csdn.net/Fly_Fly_Zhang/article/details/87865108
今日推荐