集合-ArrayList

  1. ArrayList的继承关系
    在这里插入图片描述
    继承了AbstractCollection AbstractList的类 实现了Iterable Collection List RandomAccess Cloneable Serializable接口

RandomAccess接口作用:发现实现RandomAccess接口的List集合采用一般的for循环遍历,而未实现这接口则采用迭代器

Cloneable接口作用:cloneable其实就是一个标记接口,只有实现这个接口后,在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现这个接口,则会抛出CloneNotSupportedException(克隆不被支持)异常
实现这个接口且重写clone()可以实现深度克隆和浅度克隆
浅度克隆:被克隆得到的对象基本类型的值修改了,原对象的值不会改变
深度克隆:被克隆得到的对象基本类型的值修改了,原对象的值改变

protected native Object clone() throws CloneNotSupportedException;

这是本地方法 调用的是jvm具体的方法实现

Serializable接口: 进行序列化和反序列化的时候使用 且标明一个serialVersionUID 在序列化的时候把这个id一同序列化到文件中反序列化的时候会把 serialVersionUID 同文件的id做对比 不一致则表示对象改变 序列化失败

  1. 关于ArrayList的方法讲解

底层是数组实现的

transient Object[] elementData;

transient 作用 将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。

有三个构造方法 无参 collection类型参数 int类型参数

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {  //这是jdk1.8版本的 在jdk1.7版本当无参时 默认的数组长度是10
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
 public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();  //集合对象转换为数组
        if ((size = elementData.length) != 0) {  //判断数组长度            
            if (elementData.getClass() != Object[].class){ //进行类型校验
               elementData = Arrays.copyOf(elementData, size, Object[].class); //创建一个新的的Object数组并返回
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
    
  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;
    }
	private static final Object[] EMPTY_ELEMENTDATA = {};
    public ArrayList(int initialCapacity) { //有参数时创建参数大小的数组 否则不进行指定参数大小
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

ArrayList集合的常用方法

	//set方法替换某个下标的值
  public E set(int index, E element) {
        rangeCheck(index); //大于数组的下标 报出数组越界异常
        E oldValue = elementData(index); //获取原来的旧值
        elementData[index] = element;//新值赋值
        return oldValue;//放回旧值
    } 
 private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 数组扩容
        elementData[size++] = e; //数组最后添加元素
        return true;
    }
public void add(int index, E element) {
        rangeCheckForAdd(index); //数组下标检查

        ensureCapacityInternal(size + 1);  // 数组扩容
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

 private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {   //获取最大容量值 DEFAULT_CAPACITY默认为10
            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); //右移动一位 例如2的5次方右移一位为2的4次方相当于为原来的一半 及增加原来的二分之一
        if (newCapacity - minCapacity < 0)  //如果增长得长度还是小于原来的长度则还是用原来的长度 例如默认初始值为10 但是数组的长度小于10以内
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity); //判断是否大于整数类型的最大值大于则返回整数最大值作为容量 否则最大值减8作为容量
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);  //每次返回的都是新的数组容量 的数组
    }
    
private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 按照指定collection的迭代器所返回的元素顺序,将该collection中的所有元素添加到此列表的尾部。  
public boolean addAll(Collection<? extends E> c) {  
    Object[] a = c.toArray();  
    int numNew = a.length;  
    ensureCapacity(size + numNew);  // Increments modCount  
    System.arraycopy(a, 0, elementData, size, numNew);  
    size += numNew;  
    return numNew != 0;  
}  

// 从指定的位置开始,将指定collection中的所有元素插入到此列表中。  
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);  // Increments modCount  
  
    int numMoved = size - index;  
    if (numMoved > 0)  
        System.arraycopy(elementData, index, elementData, index + numNew, numMoved);  
  
    System.arraycopy(a, 0, elementData, index, numNew);  
    size += numNew;  
    return numNew != 0;  
} 
// 返回此列表中指定位置上的元素。  
public E get(int index) {  
    RangeCheck(index);  
  
    return (E) elementData[index];  
}  
// 移除此列表中指定位置上的元素。  
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; // Let gc do its work  
  
    return oldValue;  
} 


// 移除此列表中首次出现的指定元素(如果存在)。这是应为ArrayList中允许存放重复的元素。  
public boolean remove(Object o) {  
    // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。  
    if (o == null) {  
        for (int index = 0; index < size; index++)  
            if (elementData[index] == null) {  
                // 类似remove(int index),移除列表中指定位置上的元素。  
                fastRemove(index);  
                return true;  
            }  
} else {  
    for (int index = 0; index < size; index++)  
        if (o.equals(elementData[index])) {  
            fastRemove(index);  
            return true;  
        }  
    }  
    return false;  
}  

3.快速失败
Fail-Fast机制:
ArrayList也采用了快速失败的机制,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

add、remove操作对于ArrayList其运行时间是O(N),因为在它当中在前端进行添加或移除构造新数组是O(N)操作;get方法的调用为O(1)操作。要是使用一个增强的for循环,对于任意List的运行时间都是O(N),因为迭代器将有效地从一项到下一项推进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值