欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > > 文章正文

ArrayList源码解析,arraylist源码

来源: javaer 分享于  点击 25394 次 点评:161

ArrayList源码解析,arraylist源码


一.怎么查看源码

这里先给初学者说一下,按出你的Ctrl键,鼠标移动到你想看到类,出现下划线,点进去就行了
不过此刻你要先导入你jdk文件下的src.zip文件才能够查看代码
当然你也可以直接按住Ctrl+Shift+T键弹出一个框框,输入你想查看的类名就可以了,如果并没有看到代码,也想上面一样导入jdk文件下的src.zip文件即可

这里先说明一下,这里我们查看的jdk版本是1.8

二.ArrayList源码解析

1.API中的ArrayList

2.ArrayList类定义

3.ArrayList中的全局变量

a.版本控制常量:相当于java类的身份证
private static final long serialVersionUID = 8683452581122892189L;
b.默认容量
 private static final int DEFAULT_CAPACITY = 10;
c.空的对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
d.默认的空数组
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
e.存放数据的数组的缓存变量,不可序列化
transient Object[] elementData;
f.数组的大小
private int size;

4.ArrayList中的构造方法

a.带有容量initialCapacity的构造方法
//这里参数initialCapacity是指初始化ArrayList大小
 public ArrayList(int initialCapacity) {
         //如果初始化大于0
        if (initialCapacity > 0) {
            //new 一个该大小的object数组给elementData
            this.elementData = new Object[initialCapacity];
          //如果初始化为0
        } else if (initialCapacity == 0) {
            //将空数组赋给elementData
            this.elementData = EMPTY_ELEMENTDATA;
            //当小于0时
        } else {
            //则抛出一个IllegalArgumentException异常  
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
b.无参数的构造方法
public ArrayList() {
         //直接把空数组赋给elementData
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
c.带参数Collection的构造方法

参数c为一个Collection,Collection的实现类大概有以下几种常用类型:

  • List:元素可以重复的容器
  • Set:元素不可重复的容器
  • Queue:结构是一个队列,先进先出

这个构造方法的意思是把一个Collection实现类的对象转换为ArrayList,但是c容器装的内容必须为ArrayList装的内容的子类。例如,将一个装了String内容的HashSet转换为装了String内容的ArrayList,使得ArrayList的大小和值数组都是HashSet的大小和值数组。具体实现如下代码,首先调用c(Collection的具体实现类)的toArray方法,具体大家可以看各个实现类的toArray方法,但是大概意思都是将c容器转换为object类型的数组,因为它们的返回值都是object[]。之于下面的两个判断是当得到的elementData的类名不是Object类名的时候或者是长度为0的时候才会执行。

  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 {//当size长度为0时,即elementData长度为0时
              //将空数组赋给elementData
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

5.ArrayList中的常用方法

a.size
 public int size() {
        return size;//返回ArrayList的大小
    }
b.isEmpty
public boolean isEmpty() {
        return size == 0;//判断ArrayList是否为空
    }
c.indexOf(Object o)
public int indexOf(Object o) {//查询对象o在ArrayList的位置,有位置就返回位置,没有则返回-1
        if (o == null) {
            for (int i = 0; i < size; i++)//遍历ArrayList
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)//遍历ArrayList
                if (o.equals(elementData[i]))
                     return i;
        }
        return -1;
    }
d.contains
public boolean contains(Object o) {//查询对象o是否在ArrayList存在
        return indexOf(o) >= 0;
    }
e.lastIndexOf(Object o)
public int lastIndexOf(Object o) {//返回ArrayList出现o的最后一次位置
        if (o == null) {
            for (int i = size-1; i >= 0; i--)//倒起遍历
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)//倒起遍历
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
f.trimToSize

首先在介绍这个方法的时候,要明确一点,那就是ArrayList的容量大小为size,length仅仅只是ArrayList申请的内容空间长度。ArrayList每次都会预申请多一点空间,以便添加元素的时候不需要每次都进行扩容操作,例如我们的元素个数是10个,它申请的内存空间必定会大于10,即length>size,而这个方法就是把ArrayList的内存空间设置为size,去除没有用到的null值空间。这也就是我们为什么每次在获取数据长度是都是调用list.size()而不是list.length()。

 public void trimToSize() {
        modCount++;//这个参加是从Java.util.AbstractList 继承的字段,主要是为了防止在多线程操作的情况下,List发生结构性的变化,就是防止一个线程正在迭代,另外一个线程进行对List进行remove操作,这样当我们迭代到最后一个元素时,很明显此时List的最后一个元素为空,那么这时modCount就会告诉迭代器,让其抛出异常 ConcurrentModificationException。如果没有这个参数,如果出现这种情况,系统就会抛出异常ArrayIndexOutOfBoundsException,然而抛出这个异常是不合理的,所以才定义了这样的检查
        if (size < elementData.length) {//如果size小于length
            elementData = (size == 0)//重新将elementData大小设置为size
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }
g.clone
public Object clone() {//返回此 ArrayList 实例的浅表副本。
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }
h.toArray
public Object[] toArray() {
        return Arrays.copyOf(elementData, size);//把ArrayList实例转换为Object
    }
i.toArray(T[] a)
 public <T> T[] toArray(T[] a) {//将ArrayList里面的元素赋值到一个数组中去
        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;//如果a的长度小于ArrayList的长度,直接调用Arrays类的copyOf,返回一个比a数组长度要大的新数组,里面元素就是ArrayList里面的元素;如果a的长度比ArrayList的长度大,那么就调用System.arraycopy,将ArrayList的elementData数组赋值到a数组,然后把a数组的size位置赋值为空。
    }
j.rangeCheck(int index)
private void rangeCheck(int index) {//判断下标是否超出ArrayList长度
        if (index >= size)//如果下标超出ArrayList长度就抛出异常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

相关文章

    暂无相关文章

用户点评