Java数据结构之ArrayList(4)
1. 类结构
public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable
1.1 实现接口
1.1.1 RandmoAccess接口:
是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问
想详细了解的呢可以看RandomAccess接口的使用
1.1.2 Cloneable接口:
即覆盖了函数clone(),能被克隆
1.1.3 Serializable接口
意味着ArrayList支持序列化,能通过序列化去传输
1.1.4 List接口:
在Java集合分类中,List代表有序,可重复
具体和下面父类一起说
1.2 父类AbstractList
ArrayList 继承了AbstractList,父类也实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能
1.3 它跟数组的关系?
1.3.1数组VS链表
Array(数组),数据结构适合内存结构也是连续的(适合遍历),随机访问(适合查找),不适合增删(链表则相反),同时在创建数组的同时你必须指定大小
想知道详细的可以看看数组与链表的优缺点
1.3.2 数组 VS ArrayList
- Array类型的变量在声明的同时必须进行实例化(至少得初始化数组的大小),而ArrayList可以只是先声明。
- Array只能存储同构的对象,而ArrayList可以存储异构的对象。
List内部就是使用”object[] _items;”这样一个私有字段来封装对象的) - 在CLR托管对中的存放方式:
Array是始终是连续存放的,而ArrayList的存放不一定连续。 - 初始化大小:
Array对象的初始化必须只定指定大小,且创建后的数组大小是固定的,
而ArrayList的大小可以动态指定,其大小可以在初始化时指定,也可以不指定,也就是说该对象的空间可以任意增加。 - Array不能够随意添加和删除其中的项,而ArrayList可以在任意位置插入和删除项。
同构和异构:
同构的对象是指类型相同的对象,若声明为int[]的数组就只能存放整形数据,string[]只能存放字符型数据,但声明为object[]的数组除外。
而ArrayList可以存放任何不同类型的数据(因为它里面存放的都是被装箱了的Object型对象,实际上Array
回到正文了,去看看ArrayList源码罗
2. 探索源码
2.1 构造
// ArrayList带容量大小的构造函数。 public ArrayList(int initialCapacity) { super(); if (initialCapacity
2.2添加
/** * 添加一个元素 */ public boolean add(E e) { // 进行扩容检查 ensureCapacity( size + 1); // Increments modCount // 将e增加至list的数据尾部,容量+1 elementData[size ++] = e; return true; } /** * 在指定位置添加一个元素 */ public void add(int index, E element) { // 判断索引是否越界,这里会抛出多么熟悉的异常。。。 if (index > size || index
2.3 删除
/** * 根据索引位置删除元素 */ public E remove( int index) { // 数组越界检查 RangeCheck(index); modCount++; // 取出要删除位置的元素,供返回使用 E oldValue = (E) elementData[index]; // 计算数组要复制的数量 int numMoved = size - index - 1; // 数组复制,就是将index之后的元素往前移动一个位置 if (numMoved > 0) System. arraycopy(elementData, index+1, elementData, index, numMoved); // 将数组最后一个元素置空(因为删除了一个元素,然后index后面的元素都向前移动了,所以最后一个就没用了),好让gc尽快回收 // 不要忘了size减一 elementData[--size ] = null; // Let gc do its work return oldValue; } /** * 根据元素内容删除,只删除匹配的第一个 */ public boolean remove(Object o) { // 对要删除的元素进行null判断 // 对数据元素进行遍历查找,知道找到第一个要删除的元素,删除后进行返回,如果要删除的元素正好是最后一个那就惨了,时间复杂度可达O(n) 。。。 if (o == null) { for (int index = 0; index
2.4 更新
/** * 将指定位置的元素更新为新元素 */ public E set( int index, E element) { // 数组越界检查 RangeCheck(index); // 取出要更新位置的元素,供返回使用 E oldValue = (E) elementData[index]; // 将该位置赋值为行的元素 elementData[index] = element; // 返回旧元素 return oldValue; }
2.5查找
/** * 查找指定位置上的元素 */ public E get( int index) { RangeCheck(index); return (E) elementData [index]; } public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { if (o == null) { for (int i = 0; i
3. ArrayList3种遍历方式
(01) 第一种,通过迭代器遍历。即通过Iterator去遍历。
Integer value = null; Iterator iter = list.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }
(02) 第二种,随机访问,通过索引值去遍历。
由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。
Integer value = null; int size = list.size(); for (int i=0; i
4 总结
ArrayList和LinkedList的区别
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
- 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
- 对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
ArrayList和Vector的区别
- Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同步类。因此开销就比ArrayList要大,访问要慢。正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。
- Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。
- Vector还有一个子类Stack.