您的位置:首页 > 编程语言 > Java开发

JDK1.8源码阅读记录ArrayList类

2020-03-22 18:19 453 查看

JDK1.8源码阅读记录

JAVA.Util包

ArrayList类

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList类继承AbstractList类,实现了List、RandomAccess、Cloneable、Serializable接口。
ArrayList是一个数组队列,基于数组实现。与普通数组相比,它的容量能动态扩大,简称扩容。本类继承了AbstractList类,实现了List接口,提供了相关的增加、修改、遍历、删除等功能。
它实现了RandomAccess接口,提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。即我们可以通过索引值快速获取元素对象,跟数组类似。
实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
实现java.io.Serializable接口,这意味着ArrayList支持序列化。
不过,ArrayList不是线程安全的,推荐在单线程中才使用本类。而Vector或者CopyOnWriteArrayList是线程安全的,可以在多线程中使用。

属性

/*
* 序列化ID
*/
private static final long serialVersionUID = 8683452581122892189L;

/**
* 静态变量,默认容量为10
*/
private static final int DEFAULT_CAPACITY = 10;

/**
* 空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
* 空数组,如果使用默认构造函数创建,则默认对象内容默认是该值
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
* 当前数据对象存放地方,不参与序列化,设置为default是为了简化内部类的访问
*/
transient Object[] elementData;

/**
* 包含的元素数量
*/
private int size;

构造方法

/**
* 无参构造,空数组
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_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);
}
}

/**
* 通过Collection对象构造ArrayList
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();//浅拷贝,只是将由c创建的数组地址赋给elementData
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
//深拷贝,相当于将c里面的对象复制一份到elementData中
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}

方法

public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}

自增修改次数,比较ArrayList的大小和elementData的长度,如果左边小于右边,则将elementData的长度修剪到ArrayList的大小。

public int size() { //取得大小
return size;
}
public boolean isEmpty() { //判断是否为空
return size == 0;
}
public boolean contains(Object o) { //判断是否包含某个对象
return indexOf(o) >= 0;
}
public int indexOf(Object o) {	//查找参数对象的第一个索引值,无则返回-1
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;
}
public int lastIndexOf(Object o) {	//由后向前查找参数对象的最后一个索引值,无则返回-1
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;
}
public Object[] toArray() {	//返回一个包含此列表中所有元素的数组。
return Arrays.copyOf(elementData, size);
}

位置访问操作方法

E elementData(int index) {
return (E) elementData[index];
}
public E get(int index) {
rangeCheck(index);

return elementData(index);
}

返回此列表中指定位置的元素。

改、增、删操作方法

  • 改:
    public E set(int index, E element)
  • 首先检查是否超出范围,然后用elemet替换index处的旧值,返回旧值。
  • 增:
    public boolean add(E e)
  • 在elementData的size处增加element,,即尾部增加,增加成功返回true。
  • public void add(int index, E element)
  • 从index到size-1处的元素向后移一位,然后在index处增加element。
  • public boolean addAll(Collection<? extends E> c)
  • 在ArrayList尾部增加c集合转化的数组,若有增加返回true。
  • public boolean addAll(int index, Collection<? extends E> c)
  • 将index后的元素向后移一位,然后在index处增加c集合转化的数组,若有增加返回true。
  • 删:
    public E remove(int index)
  • 从index到size-1处的元素向前一位(覆盖掉原先的元素),然后在size(大小)-1处的值设为null,返回删除的元素。
  • public boolean remove(Object o)
  • 找到参数第一次在ArrayList出现的位置index,然后从index到size-1处的元素向前一位,后在size(大小)-1处的值设为null,返回删除的元素。
  • public void clear()
  • 清空ArrayList,size为0、

  • ArrayList自己实现了 private void writeObject(java.io.ObjectOutputStream s)和 private void readObject(java.io.ObjectInputStream s) 方法
  • ArrayList基于数组方式实现,无容量的限制(会扩容)
  • 添加元素时可能要扩容(所以最好预判一下),删除元素时不会减少容量(若希望减少容量,trimToSize()),删除元素时,将删除掉的位置元素置为null,下次gc就会回收这些元素所占的内存空间。
  • 线程不安全
  • get(int index):获取指定位置上的元素时,可以通过索引直接获取(O(1))
  • remove(Object o)需要遍历数组
  • remove(int index)不需要遍历数组,只需判断index是否符合条件即可,效率比remove(Object o)高
  • contains(E)需要遍历数组
  • 使用iterator遍历可能会引发多线程异常
  • 点赞
  • 收藏
  • 分享
  • 文章举报
麻辣西瓜zero 发布了14 篇原创文章 · 获赞 0 · 访问量 369 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: