手写ArrayList

Posted xiehuazhen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写ArrayList相关的知识,希望对你有一定的参考价值。

        ArrayList是Java中最为简单也是最为常用的一个容器,那么它的内部构造是什么呢?其实ArrayList的底层实现就是数组,它的各种方法就是对数组进行的一系列操作,例如对数组元素的修改,删除,位移,对数组长度的获取等。我们可以手写一个ArrayList容器,以助我们更好的理解这个容器:

package Collection;

import java.util.Iterator;
/**
 * 深入迭代器的原理-->一个容器可以创建多个迭代器对象
 * 1.使用了内部类,实现迭代器
 * 2.使用Iterable实现foreach迭代
 * @author XieHuazhen
 *
 */

//实现Iterable接口是为了能够多一种遍历容器的方法:增强for循环
public class MyArrayList<E> implements Iterable<E>{ 
    
    //数组存储值
    private Object[] elemData;
    //容器大小
    private int size;
    
    private boolean rangeCheck(int index) {
        if(index<0||index>=size) {
            try {
                throw new IllegalArgumentException();
            }catch(IllegalArgumentException e) {
                e.printIndex();
            }
        }
        return true;
    }
    
    private void ensureCapacity() {
        if(size>=elemData.length) {
            Object[] newElem = new Object[size*2+1];
            System.arraycopy(elemData,0,newElem,0,elemData.length);
            elemData = newElem;
        }
    }
    
    public MyArrayList (int initCapacity){
        if(initCapacity>=0) {
            elemData = new Object[initCapacity];
        }else {
            try {
                throw new IllegalArgumentException();
            }catch(IllegalArgumentException e) {
                e.printCapacity();
            }
        }
    }
    
    public MyArrayList() {
        this(0);
    }
    
    public boolean isEmpty() {
        return size==0;
    }
    
    public boolean contains(Object o) {
        return indexOf(o)>=0;
    }
    
    public int indexOf(Object o) {
        for(int i=0;i<size;++i) {
            if(elemData[i].equals(o))
                return i;
        }
        return -1;
    }
    
    @SuppressWarnings("unchecked")
    public E elemData(int index) {
        return (E)elemData[index];
    }
    
    public E set(int index,Object o) {
        rangeCheck(index);
        E oldElem = elemData(index);
        elemData[index] = o;
        return oldElem;
    }
    
    public E get(int index) {
        rangeCheck(index);
        return elemData(index);
    }
    
    public void add(Object o) {
        ensureCapacity();
        elemData[size++] = o;
    }
    
    public void add(int index,Object o) {
        rangeCheck(index);
        ensureCapacity();
        System.arraycopy(elemData,index,elemData,index+1,size-index);
        elemData[index] = o;
        ++size;
    }
    
    public E remove(int index) {
        rangeCheck(index);
        E oldElem = elemData(index);
        System.arraycopy(elemData,index+1,elemData,index,size-index-1);
        elemData[--size] = null;
        return oldElem;
    }
    
    public boolean remove(E e) {
        for(int i=0;i<size;++i) {
            if(e.equals(elemData[i])) {
                remove(i);
                return true;
            }
        }
        return false;
    }
    
    //使用内部类定义iterator()
    public Iterator<E> iterator(){
        return new MyItr();
    }
    
    private class MyItr implements Iterator<E>{
        
        //计数器-->指针 游标
        private int cursor = 0;
        private int lastRet = -1;

        //判断是否存在下一个
        public boolean hasNext() {
            return cursor!=size;
        }
        
        //返回游标当前位置,并把游标移到下一位置
        @SuppressWarnings("unchecked")
        public E next() {
            if(!hasNext()) {
                try {
                    throw new IllegalArgumentException();
                }catch(IllegalArgumentException e) {
                    e.printNext();
                }
            }
            lastRet = cursor;
            return (E) elemData[cursor++];
        }
        
        //删除游标左面元素,执行完next后只能执行一次
        public void remove() {
            if(lastRet<0) {
                try {
                    throw new IllegalArgumentException();
                }catch(IllegalArgumentException e) {
                    e.printRemove();
                }
            }
            System.arraycopy(elemData,lastRet+1,elemData,lastRet,size-lastRet-1);
            cursor = lastRet;
            lastRet = -1;
            elemData[--size] = null;
        }
    }
    public static void main(String[] args) {
        
        MyArrayList<String> list = new MyArrayList<>();
        list.add("abc");
        list.add("def");
        list.add("ghi");
        list.add("jkl");
        
        //使用迭代器遍历
        for(Iterator<String> itr=list.iterator();itr.hasNext();) {
            System.out.println(itr.next());
            //itr.remove();
        }
        
        System.out.println("---------------------");
        
        //使用增强for循环遍历
        for(String str:list) {
            System.out.println(str);
        }
    }
}
package Collection;

public class IllegalArgumentException extends Exception{

    private static final long serialVersionUID = 1L;
    
    public void printCapacity() {
        System.out.println("异常,初始容量参数不合法");
        System.exit(1);
    }
    
    public void printIndex() {
        System.out.println("异常,索引范围不合法");
        System.exit(1);
    }
    
    public void printNext() {
        System.out.println("异常,无法返回当前位置元素");
        System.exit(1);
    }
    
    public void printRemove() {
        System.out.println("异常,无法移除");
        System.exit(1);
    }
}

 

以上是关于手写ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

手写数字识别——基于全连接层和MNIST数据集

前端面试题之手写promise

从0开始手写ArrayList动态数组

手写ArrayList

手写ArrayList

从0开始手写ArrayList动态数组和LinkedList双向链表