ArrayList 内部结构为一个可重复的对象数组(可存空对象)。

内部有以下几个参数:

/**
* 默认初始容量
*/
private static final int DEFAULT_CAPACITY = 10; /**
* 用于空实例的共享空数组实例
*/
private static final Object[] EMPTY_ELEMENTDATA = {}; /**
* 存储数组列表元素的数组缓冲区。数组列表的容量是这个数组缓冲区的长度
*/
private transient Object[] elementData; /**
* 数组列表的大小
*
* @serial
*/
private int size; //默认数组最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

分析几个内部方法:

1.indexOf(Object o):

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

循环对象数组进行比较,返回第一个匹配到的对象的下标,若未匹配到返回-1,提供给contains(Object o) 方法。

2.add(Object o): 添加前需要对容量进行容量检查 扩展容量。

public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保内部容量:
elementData[size++] = e; //添加元素
return true;
} //确保内部容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
} ensureExplicitCapacity(minCapacity);
}

   //确保明确的容量
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//扩展
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
     //扩展容量为之前容量的3/2 
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
     //如果扩展后的容量大于数组最大值,扩展至最大容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//
elementData = Arrays.copyOf(elementData, newCapacity);
} private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
    如果最小容量大于数组最大值,则扩展至Integer的最大值否则扩展至数组默认最大值
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

3.remove(int index):按数组下标移除对象元素,

public E remove(int index) {
    //边界检查
rangeCheck(index);
     //修改次数+1
modCount++;
E oldValue = elementData(index); int numMoved = size - index - 1;
if (numMoved > 0)
       //数组拷贝
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
     //清空最后一位
elementData[--size] = null; // clear to let GC do its work return oldValue;
}

4.remove(Object o):按对象移除,只移除匹配到的第一个相同对象

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;
} private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}

5.addAll(Collection<? extends E> c):将指定集合中的所有元素追加到数组的末尾

public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
     //扩容
ensureCapacityInternal(size + numNew); // Increments modCount
     //数组拷贝
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}

6.addAll(int index, Collection<? extends E> c):从数组的某个位置添加指定集合

public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
    
     //将集合转化为对象数组
Object[] a = c.toArray();
int numNew = a.length;
     //扩容
ensureCapacityInternal(size + numNew); // Increments modCount
     //将原数组index之后的数据拷贝至index+numNew之后
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
     //将指定数组添加至原数组
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}

进阶之路从此开始,路在脚下早已铺好,走与不走全看你想不想欣赏沿途的风景———————AmbitiousMice

List源码学习之ArrayList的更多相关文章

  1. 集合框架源码学习之ArrayList

    目录: 0-0-1. 前言 0-0-2. 集合框架知识回顾 0-0-3. ArrayList简介 0-0-4. ArrayList核心源码 0-0-5. ArrayList源码剖析 0-0-6. Ar ...

  2. JDK源码学习笔记——ArrayList/Vector

    一.类定义 public class ArrayList<E> extends AbstractList<E> implements List<E>, Random ...

  3. java集合类源码学习三——ArrayList

    ArrayList无疑是java集合类中的一个巨头,而且或许是使用最多的集合类.ArrayList继承自AbstractList抽象类,实现了List<E>, RandomAccess, ...

  4. 由JDK源码学习ArrayList

    ArrayList是实现了List接口的动态数组.与java中的数组相比,它的容量能动态增长.ArrayList的三大特点: ① 底层采用数组结构 ② 有序 ③ 非同步 下面我们从ArrayList的 ...

  5. JDK1.8源码学习-ArrayList

    JDK1.8源码学习-ArrayList 目录 一.ArrayList简介 为了弥补普通数组无法自动扩容的不足,Java提供了集合类,其中ArrayList对数组进行了封装,使其可以自动的扩容或缩小长 ...

  6. [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习)

    [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习) 在C#中,存在常见的九种集合类型:动态数组ArrayList.列表List.排序列表SortedList.哈希表HashTa ...

  7. JDK源码学习系列04----ArrayList

                                                                             JDK源码学习系列04----ArrayList 1. ...

  8. Dubbo源码学习--服务是如何引用的

    ReferenceBean 跟服务引用一样,Dubbo的reference配置会被转成ReferenceBean类,ReferenceBean实现了InitializingBean接口,直接看afte ...

  9. Dubbo源码学习--集群负载均衡算法的实现

    相关文章: Dubbo源码学习文章目录 前言 Dubbo 的定位是分布式服务框架,为了避免单点压力过大,服务的提供者通常部署多台,如何从服务提供者集群中选取一个进行调用, 就依赖Dubbo的负载均衡策 ...

随机推荐

  1. Swoole笔记(五)

    配置说明 $server->set(array( 'daemonize' => true, 'log_file' => '/www/log/swoole.log', 'reactor ...

  2. jmeter测试

    时间过得飞快,转眼间就到了公司半个月了,这是第三周上班,从上班到现在感觉自己什么都没有做,只是写了一些前台的验证,况且我的前台并不是很熟,js学了很久也快忘记了,看了看插件也不咋会用,但是自己也写了点 ...

  3. mysql一致性读

    Consistent Nonlocking Reads 一致读意味着InnoDB用多版本来提供一个查询数据库某个时间点的快照.这种查询可以看到在当前世界点之前事务提交的改变,看不到此后提交的改变,更看 ...

  4. Java学习笔记7(简易的超市库存管理系统示例)

    用以前学过的知识,可以简单地做一个超市库存管理系统: 定义一个商品类: public class FruitItem { int ID; String name; double price; int ...

  5. Git的使用-如何将本地项目上传到Github

    默认你的电脑上已经安装了git. 第一步:我们需要先创建一个本地的版本库(其实也就是一个文件夹). 你可以直接右击新建文件夹,也可以右击打开Git bash命令行窗口通过命令来创建. 现在我通过命令行 ...

  6. Gulp 插件及其使用

    前端现在有很多的自动打包工具,各有优缺点,而gulp作为其中的一员,也有着很受人们的青睐,简单粗暴,然而gulp本身并没有提供很多的API,真正的一些工作则是靠着插件完成的,本文简单介绍一些常用的gu ...

  7. spring官方学习地址

    1.http://projects.spring.io/spring-framework/ 2.https://github.com/spring-projects/spring-mvc-showca ...

  8. Kubernetes 架构(下)- 每天5分钟玩转 Docker 容器技术(121)

    上一节我们讨论了 Kubernetes 架构 Master 上运行的服务,本节讨论 Node 节点. Node 是 Pod 运行的地方,Kubernetes 支持 Docker.rkt 等容器 Run ...

  9. css样式中如何设置中文字体?

    代码如下: .selector{ font-family: SimHei,"微软雅黑",sans-serif; }  注意:加上中文名“微软雅黑”是为了兼容opera浏览器,中文字 ...

  10. 阻止a标签的默认事件及延伸

    先贴一段代码 <html lang="en"> <head> <meta charset="UTF-8"> <meta ...