Java 队列 ArrayList。简单自定义队列

第一步:查看,剖析ArrayList源代码
第二步:简单自定义队列

队列动态添加元素的机制:新建一个数组对象,再把原数组中的元素和新元素放入其中,再把新数组的地址变成原数组的地址。ArrayList的默认初始长度是10,当然也可以自定义;随着元素的增加,其长度也可能会增加,扩容的公式为:
新容量 = 旧容量/2 + 旧容量 + 1
即旧容量的1.5倍+1

泛型:泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

public class Myarraylist<E> {//指定队列中所存放对象的类型为泛型
    // 声明初始的数组名
    private Object[] array;
    // 声明数组的初始元素个数
    private int size = 0;
    // 声明数组的初始长度
    private int length = 1;

    /**
     * 构造方法
     */
    public Myarraylist() {
        array = new Object[length];
    }

    public Myarraylist(int length) {
        this.length = length;
        array = new Object[length];
    }

    /**
     * 队列扩容的方法
     */
    private void addRange() {
        Object[] newlist = new Object[(int) (1.5* length+1)];//新建一个数组
        for (int i = 0; i < array.length; i++) {//依次将旧数组的元素加给新数组
            newlist[i] = array[i];
        }
        //将旧数组变成新数组
        array = newlist;
        length = newlist.length;
    }

    /**
     * 向队列添加元素的方法
     */
    public void add(E e) {
        if (size < length) {//size小于length,可以直接加入
            array[size] = e;
            size++;
        } else {
            addRange();//扩容
            array[size] = e;
            size++;
        }
    }

    /**
     * 获取队列指定下标中元素的方法
     */
    public E get(int index) {
        rangeCheck(index);//判断下标的合理性
        return (E) array[index];
    }

    /**
     * 获取队列size的方法
     */
    public int size() {
        return size;
    }

    /**
     * 清空方法
     */
    public void clear() {
        for (int i = 0; i < size; i++) {//将所有元素设置为null
            array[i] = null;
        }
        size = 0;//将大小设置为0
    }

    /**
     * set方法
     */
    public E set(int index, E e) {
        rangeCheck(index);//判断下标的合理性
        array[index] = e;//插入元素
        return e;
    }

    /**
     * 插入方法
     */
    public void add(int index, E e) {
        rangeCheck(index);//判断下标的合理性
        if (size < length) {//判断是否越界
            size++;
            for (int i = size; i > index; i--) {//index和index后的元素全部往后挪一位,倒序
                array[i] = array[i - 1];
            }
            array[index] = e;//添加要插入的元素
        } else {
            addRange();
            size++;
            for (int i = size; i > index; i--) {
                array[i] = array[i - 1];

            }
            array[index] = e;

        }

    }

    /**
     * 移除方法
     */
    public void remove(int index) {
        rangeCheck(index);// 判断下标是否越界
        if (index == size - 1) {//如果是最后一个
            array[index]=null;
            size--;
        } else {//非最后一个移除
            for (int i = index; i < size - 1; i++) {
                array[i] = array[i + 1];
            }
            array[size - 1] = null;
            size--;
        }
    }

    /**
     * 添加数组的方法
     */
    public boolean addAll(Object[] obj) {
        int numNew = obj.length;// 获取要添加数组的长度
        if (size + numNew < length) {// 判断是否能直接加入
            for (int i = 0; i < numNew; i++) {// 依次添加数组中的元素
                array[size + i] = obj[i];
            }
            size += numNew;
        } else {// 队列长度不够,扩增队列长度
            addRange();
            for (int i = 0; i < numNew; i++) {
                array[size + i] = obj[i];
            }
            size += numNew;
        }

        return numNew != 0;
    }

    /**
     * 检查index是否越界
     */
    private void rangeCheck(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));//报数组越界异常
        }
    }

    private String outOfBoundsMsg(int index) {
        return "Index:" + index + ",Size:" + size;
    }
}

如何测试自己写的队列的功能是否实现
写一个类,创建自己定义队列的对象,往队列中存入不同的对象等数据。然后输出语句输出。查看是否有Bug,存入的数据是否和预期的相同。

猜你喜欢

转载自blog.csdn.net/lzq1326253299/article/details/82080255