java indexof源码_java1.8源码之ArrayList源码解读

文章目录

一、ArrayList概述1.1 ArrayList简介1.2 ArrayList数据结构

二、ArrayList源码分析2.1 ArrayList继承结构和层次关系2.2 类的属性2.3 构造方法2.4 主要方法2.4.1 get()方法2.4.2 set()方法2.4.3 add()方法2.4.4 remove()方法2.4.5 indexOf()和lastIndexOf()方法2.4.6 clear()方法

三、总结

一、ArrayList概述

1.1 ArrayList简介

ArrayList经常用,今天对它的源码探究一二。 一上来顶部有一大串注释,顶部注释参考了这篇博客内容如下:

List接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括null在内的所有元素。除了实现List接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于Vector类,除了此类是不同步的。) size、isEmpty、get、set、iterator和listIterator操作都以固定时间运行。add操作以分摊的固定时间运行,也就是说,添加n个元素需要O(n)时间。其他所有操作都以线性时间运行(大体上讲)。与用于LinkedList实现的常数因子相比,此实现的常数因子较低。 每个ArrayList实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。 在添加大量元素前,应用程序可以使用ensureCapacity操作来增加ArrayList实例的容量。这可以减少递增式再分配的数量。 注意,此实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。(结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用Collections.synchronizedList方法将该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问: List list = Collections.synchronizedList(new ArrayList(…)); 此类的iterator和listIterator方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的remove或add方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测bug。 此类是Java Collections Framework的成员。

顶部的注释给我们透露了几点重要信息:ArrayList是List接口的大小可变数组的实现;ArrayList允许null元素;ArrayList的容量可以自动增长;ArrayList不是同步的;ArrayList的iterator和listIterator方法返回的迭代器是fail-fast的

1.2 ArrayList数据结构

容量:CAPACITY ; 实际大小:size; ArrayList底层的数据结构就是数组,数组元素类型为Object类型,即可以存放所有类型数据。我们对ArrayList类的实例的所有的操作底层都是基于数组的。

二、ArrayList源码分析

2.1 ArrayList继承结构和层次关系

public class ArrayList extends AbstractList

implements List, RandomAccess, Cloneable, java.io.Serializable

结构图更直观些:

ArrayList:说明ArrayList支持泛型。extends AbstractList :继承了AbstractList。为什么要先继承AbstractList,而让AbstractList先实现List?而不是让ArrayList直接实现List? 这里是有一个思想,接口中全都是抽象的方法,而抽象类中可以有抽象方法,还可以有具体的实现方法,正是利用了这一点,让AbstractList是实现接口中一些通用的方法,而具体的类, 如ArrayList就继承这个AbstractList类,拿到一些通用的方法,然后自己在实现一些自己特有的方法,这样一来,让代码更简洁,就继承结构最底层的类中通用的方法都抽取出来,先一起实现了,减少重复代码。所以一般看到一个类上面还有一个抽象类,应该就是这个作用。实现了List接口:ArrayList的父类AbstractList也实现了List接口,那为什么子类ArrayList还是去实现一遍呢?collection 的作者Josh说他写这代码的时候觉得这个会有用处,但是其实并没什么用,但因为没什么影响,就一直留到了现在。实现了RandomAccess接口:表明ArrayList支持快速(通常是固定时间)随机访问。在ArrayList中,我们可以通过元素的序号快速获取元素对象,这就是快速随机访问。实现了Cloneable接口:实现了该接口,就可以使用Object.Clone()方法了。implements java.io.Serializable:表明该类具有序列化功能,该类可以被序列化,什么是序列化?简单的说,就是能够从类变成字节流传输,然后还能从字节流变成原来的类。

2.2 类的属性

// 序列化id

private static final long serialVersionUID = 8683452581122892189L;

/**

* Default initial capacity. 默认的初始化容量

*/

private static final int DEFAULT_CAPACITY = 10;

/**

* Shared empty array instance used for empty instances.

* 指定该ArrayList容量为0时,返回该空数组。

*/

private static final Object[] EMPTY_ELEMENTDATA = {};

/**

* Shared empty array instance used for default sized empty instances. We

* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when

* first element is added.

* 当调用无参构造方法,返回的是该数组。刚创建一个ArrayList 时,其内数据量为0。

* 它与EMPTY_ELEMENTDATA的区别就是:该数组是默认返回的,而EMPTY_ELEMENTDATA是在用户指定容量为0时返回。

*/

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**

* The array buffer into which the elements of the ArrayList are stored.

* The capacity of the ArrayList is the length of this array buffer. Any

* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA

* will be expanded to DEFAULT_CAPACITY when the first element is added.

* 保存添加到ArrayList中的元素。

* ArrayList的容量就是该数组的长度。

* 该值为DEFAULTCAPACITY_EMPTY_ELEMENTDATA 时,当第一次添加元素进入ArrayList中时,数组将扩容值DEFAULT_CAPACITY。

* 被标记为transient,在对象被序列化的时候不会被序列化。

*/

transient Object[] elementData; // non-private to simplify nested class access

/**

* The size of the ArrayList (the number of elements it contains).

* ArrayList的实际大小(数组包含的元素个数/实际数据的数量)默认为0

* @serial

*/

private int size;

/**

* The maximum size of array to allocate.

* Some VMs reserve some header words in an array.

* Attempts to allocate larger arrays may result in

* OutOfMemoryError: Requested array size exceeds VM limit

*/

/**

* 分派给arrays的最大容量

* 为什么要减去8呢?

* 因为某些VM会在数组中保留一些头字,尝试分配这个最大存储容量,可能会导致array容量大于VM的limit,最终导致OutOfMemoryError。

*/

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

//备注:MAX.VALUE为0x7fffffff,转换成十进制就是2147483647,也就是数组的最大长度是2147483639;

2.3 构造方法

ArrayList提供了三种构造方法:

ArrayList(int initialCapacity):构造一个指定容量为capacity的空ArrayList。这是一个带初始容量大小的有参构造函数。

初始容量大于0,实例化数组,将自定义的容量大小当成初始化elementData的大小初始容量等于0,将空数组赋给elementData初始容量小于0,抛异常

/**

* Constructs an empty list with the specified initial capacity.

* 构造具有指定初始容量的空List

* @param  initialCapacity  the initial capacity of the li

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值