Java集合(一)

Collection接口

1.继承关系

Collecton相关接口

2.实现类及方法

2.1 ArrayList

ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable,是 List 的一个实现类。

和初始化相关的一些变量

  • transient Object[] elementData;
  • private static final int DEFAULT_CAPACITY = 10//扩容时会使用
  • private static final Object[] EMPTY_ELEMENTDATA = {};
  • private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//初始化时首先会创建一个长度为0的数组,使用该静态变量赋值,为什么要再声明一个一样的空数组呢?在下面分析中看

初始化

 public ArrayList() {//空参构造函数默认创建一个空的数组,类似于懒汉式,不像jdk1.7以前初始就是长度为10
        //注意这里用到赋值的常量是DEFAULTCAPACITY_EMPTY_ELEMENTDATA
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {//传入参数大于零时建立参数大小的数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
        /*初始化长度为0的数组,和上面的空参初始化相比,虽然建的都是空数组,但是
        注意这里用到的常量是EMPTY_ELEMENTDATA*/
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
public ArrayList(Collection<? extends E> c) {//根据已有集合初始化
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            if (elementData.getClass() != Object[].class)
            //因为默认的elementData数组时Object类型,当参数集合类型不是Object类型时,转换为Object类型
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {//如果参数中集合元素为空就创建一个空数组
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

添加元素

添加单个元素

public boolean add(E e) {//添加单个元素
        ensureCapacityInternal(size + 1);//对 elementData 根据不同情况进行扩容
        elementData[size++] = e;//在在扩容后的数组elementData末尾添加元素e
        return true;//添加成功,如果这里不成功了,可能就是上面 OOM 了
    }
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//扩容
    }
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//数组 elementData 长度每次变化这个值都会 +1
        /*如果添加元素之后需要的数组实际长度,也就是传进来的参数 minCapacity 比原先的数组长度大————也就是
        数组需要扩容了,这个时候 grow*/
        if (minCapacity - elementData.length > 0)/*这时候数组 elementData 长度至少是 10 了,
        如果小于 10 时 calculateCapacity(...) 肯定返回的是 10,一定比数组长度 10 长 */
            grow(minCapacity);//实际长度超过 10 这个默认长度时进行扩容
    }
private void grow(int minCapacity) {//扩容函数
        int oldCapacity = elementData.length;//现在数组长度
        int newCapacity = oldCapacity + (oldCapacity >> 1);//按照1.5倍扩展数组
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;//扩容之后还不够不再进行1.5了,直接填满,正好就行
        if (newCapacity - MAX_ARRAY_SIZE > 0)/*MAX_ARRAY_SIZE ArrayList 最大长度
        超过这个长度造成 OOM*/
            newCapacity = hugeCapacity(minCapacity);//最高返回Integer.MAX_VALUE
        elementData = Arrays.copyOf(elementData, newCapacity);/*对数组 elementData 进行扩容,
        多余没有赋值对的部分为默认值*/
    }
private static int calculateCapacity(Object[] elementData, int minCapacity) {/*计算添加一个元素
后数组应该具有的长度*/
 		/*如果当初初始化时使用的时空参构造器,那么初始的 elementData 就是指向常量空数组
 		 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的,这种情况下返回的就是 DEFAULT_CAPACITY
 		 == 10 和添加元素后实际长度 minCapcity 中较大的数————也就是说如果初始化一个空的数组,
 		 那么当添加元素的时候,数组会按照至少长度 10 来扩容*/
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //如果初始化不是使用空参构造器创建的空数组,那么直接返回需要的实际长度作为数组 elementData 的长度
        return minCapacity;
    }

检验某个元素是否包含在列表中

public boolean contains(Object o) {/*遍历过程是通过列表元素的 equals() 方法判断的,是“内容”判断,
不是地址判等————所以添加到ArrayList中的元素一定要重写 equals 方法,否则就会判定地址,这样除了 null 元素
之外别的元素就算存在也会因为地址不同找不到了*/
        return indexOf(o) >= 0;
    }
public int indexOf(Object o) {
        if (o == null) {//元素指向 null ,搜索列表中 null,就不用调用equals了
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {//其余情况下,调用列表元素重写的 equals() 函数
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

同理,ArrayList中所有涉及到搜索比较的 remove(…),indexOf(…)等都会调用列表元素的 equals() 方法,一定记得添加的元素要重写该方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值