手写ArrayList代码package com.ykq; /** * 自己实现一个ArrayList,帮助理解ArrayList的底层结构 * @author RSA * */ public

 ArrayList的原理是数组,所以实现其add,remove,get,set等方法,仅需要考虑的是怎么在数组中实现。

另外隐含的问题是,数组在何时需要扩容,以及下标是否合法。

 

 

package com.ykq;

/**
 * 自己实现一个ArrayList,帮助理解ArrayList的底层结构
 * @author RSA
 *
 */
public class MyArrayList {
	
    //ArrayList的原理是数组
	private Object[] elementData;
	
	//List元素的个数,也可表示下一个将插入元素的下标
	private int size;
	
	//size不能直接对外,所以提供一个查询方法
	public int size() {
		return size;
	}
	
	//判断List是否为空,原理仅需判断size是否为0
	public boolean isEmpty() {
		return size == 0 ? true : false;
	}
	
	//获取List指定下标的值,原理获取数组指定下标的值
	public Object get(int index) {
		rangeCheck(index); 
		return elementData[index];
	}
	
	//删除List指定位置的对象,原理首先判断下标是否合法,再将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;
	}
	
	//删掉List某一个对象,原理将域指定对象相同的下标找出,然后调用删除List指定位置的对象的方法
	public void remove(Object obj) {
		for (int i = 0; i < size; i++) {
			if (get(i).equals(obj) ) {
				remove(i);
			}
		}
	}
	
	//为已有的下标,重新赋值,原理数组的赋值
	public Object set(int i, Object obj) {
		rangeCheck(i);
		Object oldValue = elementData[i];
		elementData[i] = obj;
		return oldValue;
	}
	
	//范围判断
	private void rangeCheck(int index) {
		//size是当前已存数据的长度,比某位元素下标多1。所以在比较时减1。为什么不需要判断index<0,原因是size本就是不小于0的,所以不用比
		if (index > size-1) {
			try {
				throw new IllegalArgumentException("下标不合法");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	//无参构造方法。将数组length设为默认值
	public MyArrayList(){
		//ArrayList的默认长度是10,为便于测试,遂初始为3
		this(3);
	}
	
	public MyArrayList(int initialCapacity){
		super();
		if (initialCapacity < 0) {
			try {
				//测试代码,没必要向上抛出异常,所以捕获
				new IllegalArgumentException("Illegle Capacity: " + initialCapacity);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		this.elementData = new Object[initialCapacity];
	}
	
	//在List末尾添加元素,原理先判断是否扩容,再在最后一位元素后赋值
	public void add(Object obj) {
		ensureCapacity();
		
		//size默认是0,意味着将入参放到当前位置
		elementData[size++] = obj;
	}
	
	//在List指定下标新查一个元素,原理判断下标是否合法,在判断是否扩容,在将index及以后的元素往后移一位,将index空出,再为下标index对应的空间赋值
	public void add(int index, Object obj) {
		rangeCheck(index);
		
		ensureCapacity();
		System.arraycopy(elementData, index, elementData, index+1, size-index);
		elementData[index] = obj;
		size++;
	}
	
	//扩容,原理新建数组,并将原数组的值赋值,再让elementData指向新数组
	private void ensureCapacity() {
		//数组扩容,原理如果标识空闲位的下标(或当前数组已存数据的长湖)size,已经等于数组定义的长度,则不够再放下一个元素,即容量不够
		if(size == elementData.length) {
			Object[] newArray = new Object[size*2+1];
			//将原数组的内容拷贝到新数组
			System.arraycopy(elementData, 0, newArray, 0, elementData.length);
			elementData = newArray;
//			两种拷贝的方法
//			for(int i = 0; i< elementData.length; i++){
//				newArray[i] = elementData[i];
//			}
			
		}
	}
	
	public static void main(String[] args) {
		MyArrayList list = new MyArrayList();
		//下面四句测试扩容
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		
		//测试下标移除
		list.remove(0);
		//测试对象移除
		list.remove("2");
		//测试为指定下标,重新赋值
		list.set(1, "5");
		//测试在指定下标插入元素
		list.add(1, "6");
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
		//测试获取指定下标的元素
		System.out.println(list.get(4));
		//测试list的元素个数
		System.out.println(list.size());
		//测试list是否为空
		System.out.println(list.isEmpty());
	}

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值