在端午节这个节日里,有一个特殊的任务,我带着你一起揭开“ArrayList”的真面目。从成员变量、构造函数、主要方法三部分,对ArrayList有进一步的认识,希望能够帮助你。

一、成员变量

   //默认容量
private static final int DEFAULT_CAPACITY = 10;
//空数组,当调用无参数构造函数的时候默认给个空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//真正保存数据的数组
private transient Object[] elementData;
//数组的大小
private int size;

transient关键字:ArrayList实现了Serializable接口,而添加上transient关键字,则elementData对象就不可以序列化。

二、构造函数

  • 无参构造方法

  • 带有容量的构造方法

  • 带参数Collection的构造方法

在参数Collection的构造方法中,只有当当得到的elementData的类名不是Object,才会执行复制操作,因为Java是动态绑定,所以getClass获取的并不一定是Object类型,有可能是它的子类。

/**
* 初始化elementData
* @param initialCapacity
*/
public ArrayList(int initialCapacity) {
super();
//如果小于0,则抛出异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//初始化elementData数组
this.elementData = new Object[initialCapacity];
} /**
* 初始化为空的对象数组
*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
} public ArrayList(Collection<? extends E> c) {
//将c容器转换为object类型的数组
elementData = c.toArray();
//更新size的大小
size = elementData.length;
//当得到的elementData的类名不是Object,才会执行复制操作
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}

三、主要方法

1、add方法

//添加元素
public boolean add(E e) {
//首先判断数组容量是否需要扩充
ensureCapacityInternal(size + 1); // Increments modCount!!
//添加元素,更新size的大小
elementData[size++] = e;
return true;
}

ArrayList相当于在没指定initialCapacity时就是会使用延迟分配对象数组空间,当第一次插入元素时ensureCapacityInternal,才分配10个对象空间。

2、get方法

 //通过下标获取元素
public E get(int index) {
//判断下标的合理性
rangeCheck(index);
//返回元素
return elementData(index);
}

3、remove方法

在remove方法中,我们需要注意对null的特殊处理。

public boolean remove(Object o) {
//如果为null对象,则特殊处理,使用==来判断
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
//如果不为null,则使用equals方法来判断。
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}

四、其他常用的方法

removeAll:移除集合A和集合B的交集,即A-B。

retainAll:保留两个集合的交集。

五、ArrayList的大小是如何自动增加的?(面试题)

  • ensureCapacityInternal    是判断是否要扩容的方法

  • ensureExplicitCapacity

  • grow 具体的扩容方法

实现思想:

  1. 确定所需minCapacity和数组当前size的关系,如果minCapacity>size,则准备grow。

  2. 如果1.5size<minCapacity,则准备扩充为minCapacity。

  3. minCapacity和MAX_ARRAY_SIZE 的关系,如果minCapacity>MAX_ARRAY_SIZE ,则需要判断minCapacity是否超出int类型所能表示的最大值。如果超出,则抛出OutOfMemoryError。

 //确保数组能够存放的:minCapacity
private void ensureCapacityInternal(int minCapacity) {
//如果elementData是空对象数组,最小容量为minCapacity和DEFAULT_CAPACITY最大值
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//判断是否需要扩容
ensureExplicitCapacity(minCapacity);
} private void ensureExplicitCapacity(int minCapacity) {
//增加被改变的次数
modCount++;
// 最小容量大于elementData的长度,则需要扩充
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} //数组的最大上限
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) {
// 数组原来的长度,保存副本
int oldCapacity = elementData.length;
//扩容至原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//判断新容量是否够用,如果不够则赋值为minCapacity
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果newCapacity超过MAX_ARRAY_SIZE
if (newCapacity - MAX_ARRAY_SIZE > 0)
//检查容量的int值是不是已经溢出。
newCapacity = hugeCapacity(minCapacity);
// 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间
// 并将elementData的数据复制到新的内存空间
elementData = Arrays.copyOf(elementData, newCapacity);
} private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

欢迎加入Java学习交流群点击:484757838 

最新文章

  1. clientX .offsetX .screenX x 的区别
  2. ZK 样式使用
  3. java 堆栈
  4. Unable to open liblaunch_sim.dylib. Try reinstalling Xcode or the simulator
  5. 重构13-Extract Method Object(提取方法对象)
  6. ffmpeg 研究
  7. HDU 5752 Sqrt Bo (数论)
  8. 第二篇、JavaScript常用的API
  9. HDOJ/HDU 2203 亲和串(简单的判断~Java的indexOf()方法秒)
  10. Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三)
  11. 犯罪团伙 codevs 3554
  12. Linux平台从文件中查找字符赋值于变量
  13. 高校表白APP-冲刺第三天
  14. 一次Linux自动化部署尝试
  15. (Beta)Let&#39;s-版本测试报告
  16. 2018牛客网暑期ACM多校训练营(第一场)E Removal(DP)
  17. MS SqlServer还原数据库,出现媒体簇的结构不正确
  18. HierarchicalClustering:编写HierarchicalClustering层次聚类算法—Jason niu
  19. C Runtime Library、C  Runtime
  20. 关于css定位

热门文章

  1. CF 690C3. Brain Network (hard) from Helvetic Coding Contest 2016 online mirror (teams, unrated)
  2. 好看的复选框(Checkbox)效果
  3. waiting for spring......
  4. oracle中varchar、varchar2、char和nvarchar的区别
  5. 【外文翻译】使用Timer类去调度任务 ——java
  6. 《分布式Java应用之基础与实践》读书笔记三
  7. Roguelike元素对游戏设计的影响
  8. Scrollview中嵌套ListView(自定义组件解决)
  9. libpng处理png图片(一)
  10. android webview和 javascript 进行交互