Java知识树 集合 ArrayList
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java知识树 集合 ArrayList相关的知识,希望对你有一定的参考价值。
简要说明
ArrayList,实现了List接口,它是一个有序集合,即元素排列的顺序和添加元素的顺序一致,我们可以通过下面的示例代码和结构图来理解刚刚这句话。
示例代码:
List<Integer> list = new ArrayList<Integer>();
list.add(6);
list.add(4);
list.add(7);
list.add(6);
list.add(1);
结构图:
通过上面的结构图我们可以知道ArrayList的底层是由数组来实现的,但它与数组的区别在于ArrayList的容量会动态增长,这意味着因存储元素导致容量不足时ArrayList会自动扩大数组的容量。这一过程的细节会在源码分析阶段进行说明。
我们在创建ArrayList时若不指定初始容量大小,则初始容量大小会默认为10,即一个能存储10个元素的数组。(注①)当然我们也可以根据实际的存储需要手动指定初始容量大小,见如下示例代码:
List<Integer> list = new ArrayList<Integer>(5);
请记住,即便指定了初始容量大小,当因存储元素导致容量不足时,ArrayList依然会自动扩容。那么这个扩容是否会有一个上限呢?答案是肯定的,具体细节会在源码分析阶段说明。
注①:在jdk1.6版本中这句话是没有问题的,但在jdk1.7版本中ArrayList()这一构造器的内部实现做了改进。可见如下源码对比:
//jdk1.6的实现 public ArrayList() { this(10); } //this(10)是调用了另外一个构造器ArrayList(int initialCapacity) public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } //this.elementData就是一个用来存储元素的数组 private transient Object[] elementData; //jdk1.7的实现 public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } //EMPTY_ELEMENTDATA是一个已经初始化了的数组,不过它的容量为0 private static final Object[] EMPTY_ELEMENTDATA = {};
我们可以对jdk1.7的改进稍作分析:当调用ArrayList()时,仅初始化了数组但并未指定容量,故此时数组的长度为0,这样做也许是为了避免存储空间的浪费。若按照之前jdk1.6的做法,只要通过ArrayList()这一构造器来创建ArrayList,那么就会初始化一个容量为10的数组,如果这个ArrayList不被使用,那么这10个容量的数组就浪费了,这样的ArrayList越多,浪费的数组也就越多。采用jdk1.7的做法虽然一样初始化了数组,但并未指定容量,这样即便创建出的ArrayList不被使用,也不至于造成存储空间的浪费。对于jdk1.7的改进我们可以提出一个疑问?通过ArrayList()这一构造器来创建ArrayList,它是在什么时候指定数组容量的呢?答案是在调用add(E e)或add(int index, E element)方法时,具体的细节会在源码分析阶段进行说明。
ArrayList实现了RandomAccess接口,提供了随机访问功能,即可以通过索引快速访问该索引所对应的元素。那么这个随机访问又是一个怎样的过程?这个问题也会在接下来的源码分析阶段得到解答。
最后需要注意的是ArrayList是非线程安全的,这意味着在多线程环境下使用它是有很大风险的。因此在多线程环境下建议使用Vector来替代它。
源码分析(基于jdk1.6.0_45)
在创建一个ArrayList时,我们需要调用它的构造器,在不指定初始容量的情况下我们可以调用ArrayList(),如果明确了要存储的元素容量,可以调用ArrayList(int initialCapacity)来创建一个带有指定容量的ArrayList。
//这虽然也是ArrayList的一个构造器,但从内部实现来看,它是调用了ArrayList(int initialCapacity)这一构造器。当我们不指定数组初始容量大小时,默认传入的initialCapacity的值是10,即一个容量为10的数组。 public ArrayList() { this(10); } public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } //用于存储元素的数组,当ArrayList的构造器被调用时进行初始化 private transient Object[] elementData;
--------------------未完,待更新--------------------
以上是关于Java知识树 集合 ArrayList的主要内容,如果未能解决你的问题,请参考以下文章