分析Collection(二)通过手写深入了解ArrayList

ArrayList

通过分析Collection(一)我们说了ArrayList的数据结构以及优缺点,今天在写一篇自己手写的ArrayList实现增删改的功能(add,remove,get),来更好的了解一下它的一些相关的实现思路

一、父类以及实现类

常用的集合

从上图可以看到,ArrayList实现了List接口。我们自己动手的话,我们让新写的类让他实现List接口。这样创建的时候就会是 List xxx = new SelfArrayList(); 这种格式了,这篇文章的代码并不是按照着jdk里面的代码写的,我们只需要实现List接口实现它里面的get,remove还有add方法就行了,然后其他的操作代码是自己想法来写,和他做到相同(不考虑线程安全的问题,也不考虑占用内存之类的,功能出来就行了。)

二、开始上手

ArrayList的数据结构是数组,我们先简单的把这个类的代码结构做出来

1.属性

看下面代码,object用来保存我们数据的一个数组,我们再定义一个size,用来保存当前咱这个List的元素的个数,说白了就是这个object的长度,至于为什么给这个数组定义为Object类型的呢??? Object是Java中所有类型它祖宗,也就是谁都可以转成Object,用列表代替数组的原因本来不就是,数组固定了存储的类型以及固定长度了吗??这里就肯定有人问,为什么不直接用Object来做数组的类型,这不就又扯出来数组不能变长度了吗,别纠结怎么多。。。

在构造函数里面创建一个Object的数组给他长度固定到3(调试的时候好看出来),然后在赋值给我们的那个object属性,当然也可以在属性里面直接写 private Object[] object = new Object[3];

public class SelfArrayList<E> implements List<E>{

	private int size; //用来保存这个列表的当前有多少元素
	private Object[] object; //用来存储数据的数组
	
	public SelfArrayList(){
		this.object = new Object[3]; //创建这个实例的时候,给这个数组固定长度,让他等于10
	}
}

2.方法

接下来开始写它的方法了,它既然有个size属性,那么肯定就会有个获取size的方法,还有它的增删改操作方法,当我们实现List类的时候,它肯定会让你实现它的全部方法,这里我们只写 size(),get(),add(),remove()这4个方法,然后我们在一步一步完善它

public class SelfArrayList<E> implements List<E>{

	private int size; //用来保存这个列表的当前有多少元素
	private Object[] object; //用来存储数据的数组
	
	public SelfArrayList(){
		this.object = new Object[15]; //创建这个实例的时候,给这个数组固定长度,让他等于10
	}

	@Override
	public int size() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public boolean add(E e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean remove(Object o) {
		// TODO Auto-generated method stub
		return false;
	}
	@Override
	public E get(int index) {
		// TODO Auto-generated method stub
		return null;
	}
}
Size方法

既然size是获取元素个数,那么就是获取数组的长度,我们直接让它返回 size就行了

	@Override
	public int size() {
		// TODO Auto-generated method stub
		return this.size;
	}
Add方法

在写删除的时候,我们要考虑到数组的长度是否够用,如果够用我们直接添加就行,如果不够用那么就该给数组扩容了,JDK中的ArrayList是原来的1.5倍,我们直接给他原来的x2就行了,不按照它的来写。。

	@Override
	public boolean add(E e) {
		// TODO Auto-generated method stub
		
		//这里就是用来判断是否超出长度了,size是我们用来记录添加的个数的
		if(this.size >= object.length) {
			Object[] temp = new Object[size * 2]; //创建一个新的数组,长度是我们当前元素个数×2
			//然后我们用arraycopy方法把object的数据复制到这个新的数组里面
			System.arraycopy(object, 0, temp, 0, size);
			//最后我们将这个临时数组赋值给原来的object,这样就完成了扩容
			object = temp;
		}
		this.object[size++] = e;  //这步就是给数组里面添加元素的,
		
		return true;
	}

this.object[size++] = e; 这个拿出来说一下

size++,先用完这个size之后在让这个size+1,可以理解为 object[size] = e; size = size + 1;
数组的下标是从0开始的,而长度是从1开始的,也就是我们取第一个数,它的下标是0,但是我们在添加一个数,就是下标(0)+1 = 1,第二个数的下标就是1了,但是它实际上是第二个,是不是发现,它的新添加的元素下标一定是它的长度,所以直接用size就是它最新元素的下标

调试

由于这个没有办法用截图完全展示出来,录制了个视频放上来

http://www.fanxing.live/video/debug-collection2.mp4

Get方法

我们前一篇文章说了,ArrayList的查询快,也就是取数据快,因为它是直接根据下标(索引)取的

    @Override
	public E get(int index) {
		// TODO Auto-generated method stub
		E value = (E) this.object[index]; 
		return value;
	}

是不是第一个想法就是这样,上面代码没有考虑一件事,如果元素只有10个,那么我们用索引查的时候查 20该怎么办??是不是肯定会超啊,所以我们应该在做个判断,看下是不是超出索引范围了,如果超出了让他抛出异常

    @Override
	public E get(int index) {
		// TODO Auto-generated method stub
		
		//定义超出索引异常
		if(index >=size || index < 0) {
			 throw new IndexOutOfBoundsException();
		}
		E value = (E) this.object[index]; //根据索引index拿到数据
		return value;
	}
调试

在这里插入图片描述

Remove方法

删除方法效率也有点慢,如果删除的数是中间的,我们不仅要考虑到前面的元素,还要考虑后面的元素

这样删除的方法也完成了,来测试一下看看效果

调试

在这里插入图片描述

    @Override
	public E remove(int index) {
		// TODO Auto-generated method stub
		if(index < 0 && index >= size) {
			throw new IndexOutOfBoundsException();
		}
		Object[] temp = new Object[size - 1]; //创建出一个比原先object数组长度少1的数组
		System.arraycopy(object, 0, temp, 0, index); //将这个指定元素前面的元素全部复制给它
		//判断这个元素是不是最后一个
		if(index < size - 1) {
			System.arraycopy(object, index + 1, temp, index, temp.length  - index);
		}
		this.object = temp;
		return (E)object;
	}

通过自己写可以发现,查询(获取)元素很快,增加和删除则非常的慢了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值