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

本文解析了Java中ArrayList的实现原理,包括构造方法、增删改查等核心操作,并讨论了顺序存储结构的特点。

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

        顺序存储结构是每个元素挨着下一个元素,存储位置连续,这种数据结构的好处就是方便获得各个元素的内存地址。在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源码后,总结如下,顺序存储结构在增删方面对资源开销比较大,因为你每增删一个元素,后面的元素必须都向前移动,但在查询方面还是比较快的,因为我们可以根据下标值去获取对应的值,这也是这种数据结构的优点,好了,本文到此,作为学习记录!




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值