六、Java集合之List

一、集合

java中集合有两个接口:Collection和Map。
Collection是一个集合接口。提供了对集合对象的基本操作和通用方法。
Collections则是一个工具类。
继承Collection接口的常用的集合Set和List接口。它们都是用来存储一组相同类型元素的数据。
Set:元素无序,不重复。
List:元素有序,可重复。

二、List接口

List接口的实现主要有ArrayList、LinkedList与Vector。

  • ArrayList:ArrayList是一个可改变大小的集合。其大小可以动态增长的,增长的大小为百分之五十。内部元素可以使用get和set方式进行访问。
  • LinkedList:LinkedList是一个可改变大小的集合。其大小也是动态增长的。是一个链表结构的集合。主要是删除和添加元素的性能要高于ArrayList,但是访问内部元素的性能比ArrayList低。
  • Vector:Vector也是一个可改变大小的集合。其大小可以动态增长,但是增长的大小为百分之百。并且Vector是线程安全的。ArrayList不是。

三、ArrayList源码

3.1 ArrayList类的继承关系

ArrayList类的继承关系如下图所示:
在这里插入图片描述
ArrayList主要是实现了Cloneable、Serializable、RandomAccess接口以及实现了AbstractList类。

  • Cloneable:这是一个标记型接口。实现了该接口则表示这类可以被clone。
  • Serializable:这个也是一个标记型的接口。实现该接口则表示这个类可以被序列化。
  • RandomAccess:这个是一个标记型接口。实现了该接口则表示这个类支持快速访问。
  • AbstractList:这个是实现了List接口的抽象类,AbstractList中实现了一些List的基本实现。

3.2 ArrayList中的属性

ArrayList中的主要属性如下:
在这里插入图片描述

  • DEFAULT_CAPACITY:默认的初始化ArrayList大小。
  • elementData:ArraryList中存储的数组缓存。
  • EMPTY_ELEMENTDATA:用于创建实例的时候将这个空的数组复制给elementData。
  • DEFAULTCAPACITY_EMPTY_ELEMENTDATA:用于创建实例的时候将这个空的数组复制给elementData,和EMPTY_ELEMENTDATA区别就是在于这个是无参构造函数时候赋值。
  • size:当前ArrayList的大小(java 成员变量int型,默认值是0)。

3.3 构造方法

ArrayList的主要的构造方法有下面几个:
在这里插入图片描述

  • 无参构造方法:无参构造方法主要是将 默认的空的元素数组赋值给了变量elementData。
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
  • 参数为int的构造方法:构造方法参数为int,int是指定初始化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);
        }
    }
  • 参数为集合的构造方法:构造方法的参数为Collection的集合。
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

3.4 ArrayList的常用方法

3.4.1 ensureCapacity

ensureCapacity是确定当前容纳的元素的数量是不是大于指定最小的容量。

    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

判断当前的的的数组是不是初始化的DEFAULTCAPACITY_EMPTY_ELEMENTDATA,是则返回0,不是返回默认大小。然后判断指定的最小容量是否大于minExpand。假设当前的数组的长度小于需要扩展的容量大小,则会变成数组elementData的数组长度。

3.4.2 grow

grow是对ArrayList里面数组容量的扩展,此方法是私有化的,仅在ArrayList里面使用。

    private void grow(int minCapacity) {
        // overflow-conscious code
        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);
    }

核心就是在新的长度是老的长度加上老的长度的右移一位(即老的长度的1.5倍),判断新的长度是否大于指定的容量,假设大于则使用新计算的长度为elementData数组的长度,反之则使用指定长度为elementData的长度。

3.4.3 contains/indexOf

contains/indexOf的参数都是一个指定的对象,主要的作用就是判断当前的对象是不是在这个元素elementData数组中。

    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;
    }

3.4.4 toArray

toArray是将当前的的list转换成泛型数组。方法参数是一个泛型的数组。

    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

3.4.5 get

get是返回elementData指定下表的元素。方法参数是一个int型的下标。返回一个泛型。

    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

判断指定下标是否超过了当前的list的大小,超过则抛出异常。

3.4.6 add

add是添加一个指定的泛型的元素到数组elementData中。

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

3.4.7 remove

remove是删除第一个匹配的元素。方法参数是一个指定的对象。

    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;
    }

remove方法是就是遍历elementData数组,和指定对象做比较,若两个对象一样,记录当前的下标,计算出需要移动的长度,将当前对象的下标+1到当前elements最后一个元素全部往前挪一位。

3.4.8 iterator

iterator方法就是返回一个迭代器。利用迭代器操作elements数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Oak_Fei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值