您的位置:首页 > 理论基础 > 数据结构算法

数据结构之顺序存储结构(ArrayList源码分析)

2017-10-09 09:47 471 查看
        数据结构是数据在计算机内存或磁盘中的组织形式。按照逻辑结构来划分,可分为集合结构、线性结构、树形结构、图形结构;按照存储结构来划分可分为顺序存储结构和链式存储结构。以下简单介绍顺序存储结构:

        顺序存储结构是每个元素挨着下一个元素,存储位置连续,这种数据结构的好处就是方便获得各个元素的内存地址。在java中,使用这种数据结构的类有ArrayList,以下对ArrayList源码进行分析。

       打开ArrayList类,其构造方法:

       public ArrayList() {
this(10);
}
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
this.elementData = new Object[initialCapacity];
}


        当你new ArrayList()时,会调用无参构造方法,在无参构造方法中又指向有参构造方法,在有参构造方法中,指定创建长度为10的Object数组,其实数组就是顺序存储结构。分析ArrayList,无非就是其增删改查。先看看它如何添加一个数据:
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
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);
}
}
        其中size表示数组的长度,也就是ArrayList的长度,每add一次,size就加1,再看ensureCapacity()方法,首先是对原始数组长度和现在增加一个后的长度做对比,如果现在的长度已经大于原始的长度了,就必须对原来数组进行扩容,int newCapacity = (oldCapacity * 3)/2 + 1;然后把原始数组复制到新长度的数组里面,elementData = Arrays.copyOf(elementData, newCapacity);这个就是添加一个数据的过程。好,接下来看一下删除一个数据的过程:
public E remove(int index) {
RangeCheck(index);

modCount++;
E oldValue = (E) elementData[index];

int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work

return oldValue;
}
        首先,是根据下标值index来删除,先用RangeCheck()这个方法判断你传入的index是否越过你数组的长度,如果越过了就会报IndexOutOfBoundsException异常,没有的话就进行删除操作;int numMoved = size - index - 1;其中numMoved是表示删除某个元素后,需要向前移动元素的个数;如果numMoved大于0,说明你删除的不是最后一个元素,需要移动你删除那个元素后面的其他元素;
System.arraycopy(elementData, index+1, elementData, index,numMoved);这句代码的意思就是把原数组删掉你要删除的元素,然后这个删除的元素后面的元素全部往前移动一位,构成新的数组重新赋给elementData;这就是ArrayList删除一个元素的过程。

        接下来,看一下ArrayList获取数据的方法:

public E get(int index) {
RangeCheck(index);

return (E) elementData[index];
}        这个比较简单,同样先判断你传入的index是否会脚标越界,不会的话直接返回数组里面index对应的值。
        接着看,ArrayList修改的数据的方法:

public E set(int index, E element) {
RangeCheck(index);

E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}

       根据index来修改对应的值,把新的值直接赋给elementData[index],达到修改的目的。
       当然,ArrayList还有很多方法,在这里就不细细分析了。在看ArrayList源码后,总结如下,顺序存储结构在增删方面对资源开销比较大,因为你每增删一个元素,后面的元素必须都向前移动,但在查询方面还是比较快的,因为我们可以根据下标值去获取对应的值,这也是这种数据结构的优点,好了,本文到此,作为学习记录!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息