Java基础二--容器ArrayList

List的实现类有两个: ArrayList(底层数组实现的)和LinkedList(底层是链表实现的)

ArrayList:由于它的底层实现是数组,所以它的大多数方法与数组下标的操作相关。可能对JDK源码感兴趣的同学有这方面的体会,今天我们就以自己的方式实现一个简单的ArrayList(需要注意的是,这里并不会实现所有的方法,而且在方法的优劣性上肯定是不足以媲美JDK源码的),这里主要是让大家对ArrayList的理解不单单停留在增,删,改的层面上
先看一下JDK源码中ArrayList的方法(我们可以看到它的方法非常的多,但在实际应用中并不是全部都需要掌握,我们只需要理解几个重要的方法,那么用起ArrayList就相当得心应手了)
在这里插入图片描述
先定义两个变量
private Object[] elementData;
private int size;(由于ArrayList的底层实现是数组应该先定义一个Object类型的数组对象)

第一个方法:检查下标是否合法

代码的实现思路:
是传入某个具体的下标,判断它是否合法(若为负数或者是超过容器的长度都是不合法)。虽然它的实现相当简单,不过由于很多方法都是基于下标操作的,所以它也显得十分重要。

private  void rangeCheck(int index) {
		if(index<0||index>=size) {
			try {
				System.out.println("越界了");
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

第二个方法:给容器添加对象(末尾)

代码实现思路:添加某个元素时:
1.我们应该首先判断容器的大小,如果没有超过预先设置好的数组长度,那我们直接在数组的下一位增加一个值即可.
2.如果添加时,发现它的长度已经超过预先数组设置的长度时,我们就应该先对数组进行扩容。
1)扩容时,由于定义时数组的长度是定长。这时我们只能通过重新建立一个新数组,然后再把老数组复制到新数组上, 这就实现 了数组的扩容了。
2)在这里我们运用了System为我们封装好的数组复制方法**:public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)**

src:源数组
srcPos:从源数组的起始位置开始
dest:目标数组
destPos:目标数组的开始位置
length:要copy数组的长度

public void add(Object obj) {
		//数组扩容和数据的拷贝
		if(size==elementData.length) {
			Object[] newArray=new Object[size*2+2];
			System.arraycopy(elementData, 0, newArray, 0, elementData.length);
			elementData=newArray;
		}
		elementData[size++]=obj;
	}

第三个方法:给容器指定的为添加对象

代码的实现思路:给容器指定的位置添加对象时,
1)我们应该先进行插入的下标位置检查,如果添加操作时的长度没有超过预先设置好的数组长度,那么直接在指定位置添加即可,
2)如果超过指定长度,那我们应该进行数组扩容后,再把元素添加到指定的位置

public void add(int index,Object element) {
		if(index>size||index<0) {
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		//数组扩容和数据的拷贝
		if(size==elementData.length) {
			Object[] newArray=new Object[size*2+2];
			System.arraycopy(elementData, 0, newArray, 0, elementData.length);
			elementData=newArray;
		}			
		System.arraycopy(elementData, index, elementData, index+1, size-index);
		elementData[index]=element;
		size++;
	}

上面的代码中比较有疑惑的应该还是添加新元素时进行的数组拷贝:System.arraycopy(elementData, index, elementData, index+1, size-index),各参数值的确定。

elementData:表示原来的数组
index:表示从index的位置开始的数据都要往后挪(因为它插入时时的下标为index)
elementData:表示原来的数组
index+1:表示挪动时新开始的位置
size-index:表示需要移动的长度

它的示意图如下:
在这里插入图片描述
第四个方法:移除指定下标的对象

代码的实现思路:先检查传入的下标是否越位,然后再进行数组之间的拷贝。
实现的示意图如下:
在这里插入图片描述

public void remove(int index) {
		rangeCheck(index);
		//删除指定位置的对象
		int numMoved=size-index-1;
		if(numMoved>0) {
			System.arraycopy(elementData, index+1, elementData, index, numMoved);
		}
		elementData[--size]=null;
	}

第五个方法:移除指定对象

代码实现思路: 遍历整个数组,用equal()方法匹配到相同的元素就可以调用上面封装的的remove()方法

public void remove(Object obj) {
		for(int i=0;i<size;i++) {
			if(get(i).equals(obj)) { //注意底层调用的是equal方法
				remove(i);
			}
		}
	}

上面是比较常用的五个方法的实现,如果有更好的想法可以直接在评论区留言。
下一节我们将会讲解LinkedList

发布了19 篇原创文章 · 获赞 2 · 访问量 424

猜你喜欢

转载自blog.csdn.net/TheWindOfSon/article/details/103131588