List接口实现类ArrayList之浅谈
来源:互联网 发布:python调用caffemodel 编辑:程序博客网 时间:2024/05/07 12:15
ArrayList和HashMap一样,在大家的平时编程中,经常被使用,算是使用率最高的容器了,ArrayList其实内在就是一个数组,现在我来简要介绍一下ArrayList其内部的原理和核心技术。
首先ArrayList内部使用的是一个数组来存储数据,然后还有一个size成员变量来记录该List中已经存放的数据个数。
我们知道,数组是固定长度的,在定义之初就定义好的,那为什么ArrayList在使用的时候,不用考虑这个数组越界等问题呢?其实在ArrayList里面有一个方法,就是
ensureCapacity,具体实现定义如下
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
这个方法是用于在队列长度不够的时候,自动扩充队列长度的,每次扩充的比例是老长度*3/2 + 1,也就是说将老的长度扩大1.5倍,并且再加1,这个为什么以这个比例来扩展,背景和原因不太清楚。
接着,我们来看下里面的具体方法的实现
trimToSize
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
}
这个方法的目的就是将这个List内部的数组后面空的对象直接移除掉,类似String的trim方法,可以节省空间。比如这个List内部的数组已经定义为了32的长度,但是实际内部只放了12个数据,那么这个时候,调用了这个方法之后,会重新申请一个12长度的数组,将原来数组中的12个数据拷贝过来,然后将原来的32长度的数组destroy。
接着,我们看下indexOf方法的实现
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;
}
这个方法,其实就是遍历数组,然后找到内容是一样的对象出来,不过这里需要注意的一点就是,ArrayList的元素是可以重复的,所以这里找到的也是第一个匹配的记录。
既然有indexOf,而且元素又是可以重复的,所以必然也就有一个lastIndexOf
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
这个的实现思路和上面的方法类似,只是从数组的最后面查询起。
接下来需要关注的是几个toArray的方法,这里,通过看内部的实现可以知道,其实返回的是一个新的数组,并且是通过内存拷贝的方式,具体的方法有
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
后面的add方法和set方法如下
public E set(int index, E element) {
RangeCheck(index);
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
这两个方法也没啥技术含量,对于set方法来说,就是先检测一下这个index是否合法,如果不合法,就抛出异常,否则就将这个位置的数据替换掉,同时返回老数据。
对于add方法,则是先对长度+1做一次ensureCapacity,可能有概率会扩充这个数组长度,然后将数据追加到数组的有数据的最后一个位置的后面。
后面的remove等方法就不继续介绍了,只要知道了ArrayList其实内部就是一数组,并且会自动扩展长度,最后对外呈现就是一个不需要关心其长度的List,其他的一些方法就逗比较好理解了。
最后有一个问题需要特别说明,就是如果在new的时候不指定初始化长度,那么默认给的长度就是10,所以一般推荐大家在new一个ArrayList的时候,一定要指定一下初始化长度,减少ArrayList自己去扩充长度照成的内存、性能的浪费。
- List接口实现类ArrayList之浅谈
- 浅谈List接口 自己实现ArrayList LinkedList主要方法
- List接口实现类(1):ArrayList
- JavaSE入门学习35:Java集合框架之List接口及其实现类ArrayList和LinkedList
- Java集合之三List接口及其实现类ArrayList、LinkedList、Vector
- java之List的实现类ArrayList
- List接口及其实现类——ArrayList
- 集合(1)—List接口的实现类ArrayList
- (Java笔记)List接口及其实现类---ArrayList
- Thinking in Java之List接口、ArrayList类源码学习
- java程序员从笨鸟到菜鸟之(二十五)集合之List接口的子实现类ArrayList,LinkedList,Vector
- List<?> list= new ArrayList<?>为什么这样写 接口引用指向实现类的对象
- List list = new ArrayList()等接口 new 实现类()的作用
- 集合:List实现类ArrayList
- List接口和ArrayList类练习
- List接口和ArrayList类练习
- List接口ArrayList
- ArrayList既然继承自AbstractList抽象类,而AbstractList已经实现了List接口,那么ArrayList类为何还要再实现List接口呢?
- 在内核外编写的linux驱动程序MAKEFILE
- _luce_ne+IK_analyzer
- 如意淘商品推荐技术介绍之二:高级技术
- Eclipse开发明明没错报红叉错误
- C#中的Panel滚动条控制
- List接口实现类ArrayList之浅谈
- windows上如何用HDC获得某张图片上某个点的像素值
- 淘宝搜索算法综述之一:淘宝搜索的特点
- CSDN上Android与IPhone开发博客精选
- sqlite3常用命令&语法
- eclipse 快捷键配置文件备份
- x264参数介绍(一、帧类型和码率控制)
- TinyXml使用方法
- OC 冒泡排序 ——时间排序