本文原创地址, 我的博客 : https://jsbintask.cn/2019/03/22/jdk/jdk8-arraylist/ (食用效果最佳),转载请注明出处!
ArrayList 是一个长度可调节的数组,使用者只需向其中添加,删除,获取元素,可以向其中添加任何对象(包括null值),无需关系它的扩容,,缩减问题。它实现了 list 接口所有方法,它基本等价于 Vector ,唯一不同的是它没有任何同步手段,多线程环境须慎重考虑。
这里唯一需要注意的是,它实现了一个 RandomAccess 接口,这个接口没有任何方法声明,是一个标记接口,它是为了告诉使用者如果实现了这个接口那么你的实现在算法上应该for循环会比使用iterator更快, LinkedList 则没有实现这个接口,它则是iterator更快。
我们查看Collections工具类二分搜索方法:
这就验证了我们上面说的那句话,实现了这个接口的子类在随机访问时会更快(for循环),而没有实现,则顺序访问会更加快(iterator迭代)。
它内部主要有两个成员变量,elementData用于存储数据,size用于标记存储了多少个元素,size总是按最大值显示的(考虑多线程环境,添加元素先增加size)。
add(E e) 末尾插入新元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); //判断是否需要扩容
elementData[size++] = e;
return true;
}
从这里我们知道每次扩容后的大小为原来的容量 n + n/2,例如原来的容量是10,扩容后的容量则成了15. add(int index, E e) 指定位置插入新元素
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
其它的add方法同上类似,这里不再赘述。 get(int index)
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
获取指定位置元素,直接返回数组对应的位置,不需要额外操作,很快!(这也是为什么它能够实现了AccessRandom)
remove(int index)
public E remove(int index) {
rangeCheck(index);
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;
}
index(E e) 查询元素位置
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;
}
遍历查找第一个equals要找的的元素的位置,返回,简单粗暴。
最后我们介绍下另一个方法trimToSize() :
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
这个方法是用来缩减空间的,当你的ArrayList装的东西已经确定以后(以后不会再删除,添加),可以调用这个方法节省内存空间。 它会把数组的长度缩减得和size一样。
关注我,这里只有干货! 谢谢你支持我分享知识
扫码打赏,心意已收
打开 微信 扫一扫,即可进行扫码打赏哦