JAVA容器-模拟ArrayList的底层实现
概述
ArrayList实质上就是可变数组的实现,着重理解:add、get、set、remove、iterator的实现,我们将关注一下问题。
1、创建ArrayList的时候,默认给数组的长度设置为10。
2、当set、remove、set的时候,如何解决越界问题?
3、当add的时候,如何解决扩容问题?
4、由于数组是不可变的时候,我们需要频繁重新新建数组重新赋值。
模拟实现
1、ArrayList定义变量与初始化。
//定义存储数据的数组 private transient Object [] elementData; //容量大小 private int size; //默认构造器设置数组长度为10 public MyArrayList() { this(10); } public MyArrayList(int capacity) { super(); if(capacity<0){ throw new IllegalArgumentException("数字不能小于0"); } elementData=new Object[capacity]; }
2、解决越界问题:当索引值小于0或者索引值大于等于size就将越界。
public void rangeCheck(int index){ if(index<0 ||index>this.size){ throw new IndexOutOfBoundsException("越界"+index); } }
3、解决扩容问题:普通扩容(new=old+old*2)、索引值依然大于普通扩容(new=index)、当超过int的取值范围(int的最大范围-8)
public void ensureCapacity(int minCapacity){ if(minCapacity>elementData.length){ //获得初始容器大小 int oldCapacity=elementData.length; //新的容器大小:初始容器大小+2初始容器大小(不懂为啥这样加) int newCapacity=oldCapacity+(oldCapacity>>1); //当新增以后,还不能满足索引长度,即将数组设置为最小索引长度 if(newCapacity<minCapacity){ newCapacity=minCapacity; } //当超过int的范围的时候 if(minCapacity>Integer.MAX_VALUE-8){ newCapacity=Integer.MAX_VALUE-8; } Object [] elments=new Object[newCapacity]; //创建新的数组重新赋值。 System.arraycopy(elementData,0,elments,0,size); elementData=elments; } }
4、谈谈迭代器:hasNext():判断是否有下一个、next():当前游标指向的值、remove():删除刚变过过的元素;
private class Iter implements Iterator{ //游标 private int cursor=0; //指向刚遍历过的元素 private int lastRet=0; public boolean hasNext() { return size!=cursor; } public Object next() { int i =cursor; if(i>=size){ throw new NoSuchElementException(); } cursor=i+1; return elementData[lastRet=i]; } public void remove() { if(cursor<0){ new IllegalThreadStateException(); } MyArrayList.this.remove(cursor); cursor=lastRet; //当删除一个元素的时候,赋值为0 lastRet=-1; } }
5、我相信乐忠于理解源码的同学的基础,弄清楚以上问题,应该ArrayList就没有问题了。
public class MyArrayList<E> { //定义存储数据的数组 private transient Object [] elementData; //容量大小 private int size; //默认构造器设置数组长度为10 public MyArrayList() { this(10); } public MyArrayList(int capacity) { super(); if(capacity<0){ throw new IllegalArgumentException("数字不能小于0"); } elementData=new Object[capacity]; } public E get(int index) { rangeCheck(index); return (E) elementData[index]; } public void set(int index, E element) { rangeCheck(index); ensureCapacity(index+1); E oldVlue= (E) elementData[index]; this.elementData[index]=element; } public void add(E e) { ensureCapacity(size+1); elementData[size]=e; size++; } public void add(int index, E element) { rangeCheck(index); ensureCapacity(index+1); //动态数组 System.arraycopy(elementData,index,elementData,index+1,size-index); elementData[index]=element; size++; } //移除 public void remove(int index) { rangeCheck(index); E oldVlue= (E) elementData[index]; int moved=size-index-1; if(moved>0) System.arraycopy(elementData,index+1,elementData,index,size-index);
elementData[--size]=null; } //判断是否越界 public void rangeCheck(int index){ if(index<0 ||index>this.size){ throw new IndexOutOfBoundsException("越界"+index); } } //扩容 public void ensureCapacity(int minCapacity){ if(minCapacity>elementData.length){ //获得初始容器大小 int oldCapacity=elementData.length; //新的容器大小:初始容器大小+2初始容器大小(不懂为啥这样加) int newCapacity=oldCapacity+(oldCapacity>>1); //当新增以后,还不能满足索引长度,即将数组设置为最小索引长度 if(newCapacity<minCapacity){ newCapacity=minCapacity; } //当超过int的范围的时候 if(minCapacity>Integer.MAX_VALUE-8){ newCapacity=Integer.MAX_VALUE-8; } Object [] elments=new Object[newCapacity]; //创建新的数组重新赋值。 System.arraycopy(elementData,0,elments,0,size); elementData=elments; } } public int size(){ return size; } public Iterator iterator(){ return new Iter(); } private class Iter implements Iterator{ //游标 private int cursor=0; //指向刚遍历过的元素 private int lastRet=0; public boolean hasNext() { return size!=cursor; } public Object next() { int i =cursor; if(i>=size){ throw new NoSuchElementException(); } cursor=i+1; return elementData[lastRet=i]; } public void remove() { if(cursor<0){ new IllegalThreadStateException(); } MyArrayList.this.remove(cursor); cursor=lastRet; //当删除一个元素的时候,赋值为0 lastRet=-1; } } public static void main(String [] args){ MyArrayList ls=new MyArrayList(); ls.add(123); ls.add(123); ls.set(0,456); ls.remove(1); System.out.println(ls.size()); System.out.println(ls.get(0)); Iterator it=ls.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }