博客园 首页 私信博主 显示目录 隐藏目录 管理

自己实现基于数组的ArrayList的基本api


写一个自己的ArrayList
* 集合类 容器
*
* 1 里面提供了哪些操作? 参考List接口
*
* 2 里面有哪些数据? 成员变量 分析
*
* 3 构造方法;

接口List

import java.util.Iterator;
import java.util.ListIterator;

public interface List<E> {
    boolean add(E e);

    void add(int index,E e);

    void remove(E e);

    E remove(int index);

    boolean contains(E e);

    void clear();

    E get(int index);

    int indexof(E e);

    int lastIndexof(E e);

    void set(int index,E e);

    int size();

    boolean isEmpty();

    ListIterator<E> iterator();

    ListIterator<E> iterator(int index);
}

Test

package javahomework.day29;

import java.util.ListIterator;

public class Test {
    public static void main(String[] args) {
        MyList<String> ms = new MyList<>();
        boolean empty = ms.isEmpty();
        //System.out.println(empty);
        ms.add("a");
        ms.add("b");
        ms.add("d");
        ms.add("e");
        ms.add("a");
        System.out.println(ms.size);

        //ms.remove(1);
        System.out.println(ms);

        ListIterator listIterator = ms.iterator();
        while(listIterator.hasNext()){
            Object next = listIterator.next();

            if("a".equals(next)){
                ms.remove(next);
                //listIterator.add("java");
            }
        }
        while(listIterator.hasPrevious()){
            Object previous = listIterator.previous();

            if("a".equals(previous)){
                //listIterator.add("java");
            }
        }
        System.out.println(ms);
    }
}

  

 

MyList

package javahomework.day29;


import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.ListIterator;
import java.util.NoSuchElementException;

/*
 * 写一个自己的ArrayList
 */
public class MyList<E> implements List<E> {

    public Object[] element;//存储数据的数组

    int size;//数据元素的个数

    int modecount;//集合修改的次数

    private static final int Defaultcapcity = 10;  //默认分配的容量
    private static final int Max_arry = Integer.MAX_VALUE-8;//最大数组容量

    //无参构造,分配默认的容量Defaultcapcity
    public  MyList(){
        element = new Object[Defaultcapcity];
    }

    //有参构造,分配指定容量
    public MyList(int capcity) {
        //判断参数是否合法
        if(capcity<0||capcity>Max_arry){
            throw new IllegalArgumentException("非法参数");
        }
        element = new Object[capcity];
    }

    /**
     * toString方法 把集合元素输出
     * @return  返回集合元素的字符串
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        if(size>0){
            for(int i =0; i < size-1; i++){
                sb.append(element[i]+" ");
            }
            sb.append(element[size-1]);
        }

        sb.append("]");
        return sb.toString();
    }

    /**
     * 在集合末尾增加一个元素
     * @param o  任意指定类型
     * @return  返回true添加成功
     */
    @Override
    public boolean add(Object o) {

        add(size,o);
        return true;
    }

    /**
     * 在index位置添加元素
     * @param index  集合的索引位置
     * @param o   任意类型数据
     */
    @Override
    public void add(int index, Object o) {
        checkIndex(index);   //检查索引是否合法

        int mincapcity = size+1;  //要添加元素,那么最小容量至少为size+1

        if(mincapcity>element.length){  //判断最小需要的容量与分配的容量的大小,决定是否需要扩容

            int newcapcity = element.length+(element.length<<1);  //新的容量一般为原容量的1.5倍
            if(newcapcity<0||newcapcity>Max_arry){    //如果新的容量不符合容量的要求
                newcapcity = Max_arry;                //直接把新的容量设为容量最大值
            }
            if(mincapcity>newcapcity){                //计算好新的容量后,比较最小需要的容量和新的容量,二者的较大值才为需要的新的的容量
                newcapcity= mincapcity;
            }
            Object[] objects = new Object[newcapcity];//用需要的容量创建新的数组
            for(int i=0;i<newcapcity;i++){            //新的数组存入element数组的数据
                objects[i] = element[i];
            }
            element = objects;                        //element数组指向新数组引用
        }



        for(int i = size; i>index; i--){              //开始添加数据,首先把添加位置后的数据都向后移动
            element[i] = element[i-1];
        }

        element[index] = o;                           //在要添加的位置添加数据
        modecount++;                                  //修改集合次数+1
        size++;                                       //集合元素个数+1
    }

    /**
     * 检查索引是否合法
     * @param index  索引
     */
    private void checkIndex(int index) {
        if(index<0||index>size){
            throw new IllegalArgumentException("非法参数");
        }
    }

    /**
     * 移除指定元素(有重复的移动位置最前的)
     * @param o
     */
    @Override
    public void remove(Object o) {

        int index = indexof(o);
        if(index!=-1){      //如果索引可以找到
            remove(index);
        }
    }

    /**
     * 移除指定位置的元素
     * @param index 索引
     * @return 返回移除的元素
     */
    @Override
    public E remove(int index) {
        checkIndex(index); //检查索引是否合法

        E e = (E) element[index];  //临时保存所移除元素
        for (int i = index; i <size ; i++) {  //移除元素,需要把index之后的 元素向前移动
            element[i] = element[i+1];
        }
        element[size] = null;      //移除后空出位置需要置为空

        size--;                    //元素个数-1
        modecount++;               //修改集合次数+1
        return e;
    }

    /**
     * 判断集合中是否包含此元素
     * @param e  任意类型数据
     * @return  返回true表示找到,否则返回false
     */
    @Override
    public boolean contains(E e) {
        int i = indexof(e);
        return i!=-1;
    }

    /**
     * 清空集合元素
     */
    @Override
    public void clear(){
        for (int i = 0; i < size; i++) {
            element[i] =null;               //所有元素置为空
        }
        size = 0;                           //元素个数置为0
        modecount++;                        //修改集合次数+1
    }

    /**
     * 得到集合指定位置的元素
     * @param index  索引
     * @return  返回指定位置的元素
     */
    @Override
    public E get(int index) {
        checkIndex(index);         //判断索引是否合法
        return (E) element[index];
    }

    /**
     * 找到指定元素的位置
     * @param o 任意类型
     * @return 找到返回元素位置,否则返回-1
     */
    @Override
    public int indexof(Object o) {

        for (int i = 0; i < size; i++) {
            if(element[i].equals(o)){
                return i;
            }
        }
        return -1;
    }

    /**
     * 找到指定元素最后一个的位置
     * @param o 任意类型
     * @return 找到返回元素位置,否则返回-1
     */
    @Override
    public int lastIndexof(Object o) {

        for (int i = size-1; i >=0; i--) {  //从后向前找方便
            if(element[i].equals(o)){
                return i;
            }
        }
        return -1;
    }

    /**
     * 修改集合指定位置的元素
     * @param index 索引
     * @param o 任意类型
     */
    @Override
    public void set(int index, Object o) {
        checkIndex(index);    //检查索引合法性
        element[index] = o;
    }

    /**
     * 返回集合元素个数
     * @return size
     */
    @Override
    public int size() {
        return size;
    }

    /**
     * 判断集合是否为空
     * @return  为空返回true,否则返回false
     */
    @Override
    public boolean isEmpty() {
        return size==0;
    }

    /**
     * 迭代器无参构造
     * @return  ListIterator<E>
     */
    @Override
    public ListIterator<E> iterator() {
        return new MyIterator();
    }

    /**
     * 迭代器有参构造
     * @param index 索引
     * @return ListIterator<E>
     */
    @Override
    public ListIterator<E> iterator(int index) {
        return new MyIterator(index);
    }

    //成员内部类实现迭代器
    public class MyIterator<E> implements ListIterator<E> {

        int cursor;  //游标

        int lastRet=-1; //记录上一次next或previous返回元素的索引位置

        int expectedmodecount = modecount; //记录集合修改次数,用于检查是否出现并发修改

        public MyIterator(int cursor) {    //迭代器有参构造
            if(cursor<0||cursor>size){     //游标合法性,对应size
                throw new IllegalArgumentException("-1");
            }
            this.cursor = cursor;
        }

        public MyIterator() {}  //无参构造


        /**
         * 判断是否有下一个元素
         * @return 有返回true,否则返回false
         */
        @Override
        public boolean hasNext() {
            return cursor<size;  //游标对应size
        }

        /**
         *
         * @return  返回游标的下一个元素
         */
        @Override
        public E next() {

            checkBinfa();   //并发检查
            if(hasNext()){  //有下一个元素
                E e = (E) element[cursor];  //保存下一个元素
                lastRet=cursor;            //记录上一次next或previous返回元素的索引位置
                cursor++;                  //游标后移
                return e;
            }else {
                throw new NoSuchElementException();
            }

        }

        /**
         * 检查是否发生并发修改
         */
        private void checkBinfa() {
            if(expectedmodecount!=modecount){
                throw new ConcurrentModificationException();
            }
        }

        /**
         * 判断是否有前一个元素
         * @return  有的话返回true,没有返回false
         */
        @Override
        public boolean hasPrevious() {
            return cursor>0;
        }

        /**
         *
         * @return  返回游标的上一个元素
         */
        @Override
        public E previous() {
            checkBinfa();   //并发修改检查
            if(hasPrevious()){      //有上一个元素
                E e = (E) element[cursor-1];  //保存上一个元素

                cursor--;                     //游标前移
                lastRet = cursor;             //记录上一次next或previous返回元素的索引位置
                return e;
            }else{
                throw new NoSuchElementException();
            }
        }

        /**
         *
         * @return  返回对 next 的后续调用所返回元素的索引。
         */
        @Override
        public int nextIndex() {

            return cursor;
        }

        /**
         *
         * @return  返回对 previous 的后续调用所返回元素的索引。
         */
        @Override
        public int previousIndex() {
            return cursor--;
        }

        /**
         * 移除next 或者 previous 返回的最后一个位置的元素
         */
        @Override
        public void remove() {
            if(lastRet==-1){      //如果已经修改过,就不再允许在当前游标位置进行修改
                throw new IllegalStateException();
            }
            checkBinfa();               //并发修改检查
            MyList.this.remove(cursor);  //删掉
            expectedmodecount = modecount;//迭代器的自身的修改不会引发并发修改异常
            cursor = lastRet;              //这里next和previous统一处理即可
            lastRet=-1;                    //不允许在当前游标位置进行修改,如果修改就会发生逻辑错误
        }

        /**
         *  修改curcor位置的元素的值
         * @param e
         */
        @Override
        public void set(E e) {
            if(lastRet == -1){    // 如果已经修改过,就不再允许在当前游标位置进行修改
                throw new IllegalStateException();
            }
            checkBinfa();
            MyList.this.set(cursor,e);
        }

        /**
         * 在当前curcor位置添加一个元素
         * @param e
         */
        @Override
        public void add(E e) {
            if(lastRet==-1){       // 如果已经修改过,就不再允许在当前游标位置进行修改
                throw new IllegalStateException();
            }
            checkBinfa();           //并发修改检查
            MyList.this.add(cursor,e);
            expectedmodecount = modecount;//迭代器的自身的修改不会引发并发修改异常
            cursor++;                     //游标后移
            lastRet = -1;                  //不允许在当前游标位置进行修改,如果修改就会发生逻辑错误
        }
    }


}

  

posted @ 2020-08-15 17:53  hfcnal  阅读(209)  评论(0编辑  收藏  举报