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());
}

}
}

posted @ 2017-03-16 19:10  码农皮邱  阅读(568)  评论(7)    收藏  举报