ArrayList源码解析,arraylist源码
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));
}
相关文章
- 暂无相关文章
用户点评