ArrayList学习笔记
Posted 等待戈多儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList学习笔记相关的知识,希望对你有一定的参考价值。
ArrayList的数据结构比较简单,但是其中也包含了一些好的设计思想。
ArrayList是用数组实现的,因为可以自动扩容(增加50%),所以ArrayList也可以理解为动态数组。
1.初始化
ArrayList的实现也是在不断改进的。在JDK1.7之后,ArrayList初始化的时候,elementData[]数组还是空的,并没有初始化长度为10的数组(困惑良久)。
private static final int DEFAULT_CAPACITY = 10;
//无参构造方法
public ArrayList()
super();
this.elementData = EMPTY_ELEMENTDATA;
add(E e)时:
if (elementData == EMPTY_ELEMENTDATA)
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity - elementData.length > 0)
grow(minCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
当add(E e)之后,newCapacity其实就是DEFAULT_CAPACITY(10)。这样做的好处就是new ArrayList<E>()时,并没有分配内存空间给elementData[]数组。
2.transient(瞬时)
private transient Object[] elementData;
这个关键字可能不常见,但是在JDK的源码中比较常见,HaspMap中EMPTY_TABLE[]也是transient修饰的。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量。假如现在实际有了5个元素,而elementData的长度可能是10,那么在序列化时只需要储存5个元素,数组中的最后五个元素是没有实际意义的,不需要储存。所以ArrayList的设计者将elementData设计为transient,然后在writeObject方法中手动将其序列化,并且只序列化了实际存储的那些元素,而不是整个数组。
3.自动扩容(grow())
int newCapacity = oldCapacity + (oldCapacity >> 1);
elementData = Arrays.copyOf(elementData, newCapacity);
>>右移算术运算符,移动前加上符号位,负数加1,正数加0,然后移动
扩容造成的浪费可以调用trimToSize()方法:
if (size < elementData.length)
elementData = Arrays.copyOf(elementData, size);
trimToSize():应用程序可以使用此操作来最小化 ArrayList 实例的存储量。
List关注数据的索引列表。ArrayList可以通过索引快速访问数据。
以上是关于ArrayList学习笔记的主要内容,如果未能解决你的问题,请参考以下文章