手写简单的ArrayList

2019-05-23  本文已影响0人  Ethan_zyc

注释都在代码里,就是数组集合,实现简单的增删改查,考虑的没有jdk源码详细,欢迎指出bug

package com.ethanzyc.allinone.dataStructure.List;

/**
 * 手写一个数组集合
 * @author ethan
 * @date 2019/5/17 02:41
 */
public class MyArrayList<T> {
    /** array list 简单说就是内存地址在硬盘中是连续的数组 **/
    private T[] array;
    /** index相当于数组的指针,通过指针来表示数组的长度,以及定位添加的位置 **/
    private int index;

    /**
     * 数组集合无参构造函数,不指定容量就默认为10
     */
    public MyArrayList() {
        this(10);
    }

    /**
     * 数组集合指定长度构造函数
     * @param length
     */
    public MyArrayList(int length) {
        this.array = (T[]) new Object[length];
    }

    /**
     * 获取数组的长度,有多少值,size就是多少,不同于数组的容量
     * 其实是通过一个指针去控制
     * @return
     */
    public int size() {
        return index;
    }


    /**
     * 判断是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * 集合新增元素
     * @param t
     */
    public void add(T t) {
        add(t, index);
    }


    /**
     * 集合指定位置新增元素,
     * ##private##
     * @param t
     * @param index
     */
    public void add(T t, int index) {
        // 如果数组的长度等于数组的指针,就扩容
        if (array.length == size()) {
            int newLength = array.length * 2 - 1;
            enlargeList(newLength);
            System.out.println("扩容到了" + newLength);
        }
        // 如果指定的位置大于list的长度,就还是把这个值add到集合的末尾
        if (index > size()) {
            index = size();
        }
        // 如果插入的位置在他之前,就需要把他之后的元素都向后移一位,然后插入
        if (index < size()) {
            for (int i = size(); i > index-1 ; i--) {
                array[i] = array[i-1];
            }
        }
        array[index] = t;
        this.index++;

    }

    /**
     * 数组扩容
     * @param newSize
     */
    public void enlargeList(int newSize) {
        if (newSize < size()) {
            return;
        }
        T[] oldArr = array;
        array = (T[]) new Object[newSize];
        for (int i = 0; i < oldArr.length; i++) {
            array[i] = oldArr[i];
        }
    }

    /**
     * 获取下标为index的函数
     * @param index
     * @return
     */
    public T get(int index) {
        return array[index];
    }


    /**
     * 设置下表为 index 的值,并返回原来的值
     * @param index
     * @param newVal
     * @return
     */
    public T set(int index, T newVal) {
        if (index < 0 || index > size()) {
            throw  new IndexOutOfBoundsException();
        } else {
            T toReturn = array[index];
            array[index] = newVal;
            return toReturn;
        }
    }

    /**
     * 移除元素
     * 数组因为在内存中是连续的,所以删除的时候把这个元素的后一位前移一位都行
     * 这也是数组集合增删慢的原因
     * @param index
     * @return
     */
    public T remove(int index) {
        if (index < 0 || index > size()) {
            throw  new IndexOutOfBoundsException();
        } else {
            // 将后面每一位赋值到前一位
            T oldVal = array[index];

            for (int i = index; i < size()-1; i++) {
                array[i] = array[i+1];
            }

            this.index--;

            return oldVal;
        }
    }

    public static void main(String[] args) {
        MyArrayList<Integer> list = new MyArrayList<Integer>(6);

        System.out.println(list.size());

        /** test1 start**/
//        list.add(1);
//        list.add(2);
//        list.add(3);
//        println(list);
//        list.add(222,10);
//        println(list);
        /** test1 end**/

        /** test2 start**/
        list.add(1);
        System.out.println(list.get(0));
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        println(list);
//        list.enlargeList(20);
        println(list);
        Integer oldVal = list.set(3, 20);
        System.out.printf("原来的值:%d", oldVal);
        System.out.println();
        println(list);
        Integer remove = list.remove(1);
        System.out.println(remove);
        println(list);
        /** test2 end**/
    }

    private static void println(MyArrayList list) {
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i) + " ");
        }
        System.out.println();
    }

    /**
     * 基础知识:测试数组复制
     * 1.a = new int[...] 会把这个a与这个数组对象的引用断开,重新指向一个新的内存地址,
     *   但是b与a之前的数组对象还是存在引用,所以a重新分配对象并不会影响到b
     * 2.a[?] = ? 改变的仍是a指向的内存地址中的数据,由于b也是指向这个内存地址,所以这样操作会影响到b
     * @param args
     */
    public static void testCopy(String[] args) {
        int[] a = new int[]{1,2,4};
        println(a);

        int[] b = a;

        println(a);
        println(b);

        a = new int[2];
        println(a);
        println(b);

        int[] c = a;

        println(b);
        println(c);

        a[0] = 101;
        println(b);
        println(c);


    }

    private static void println(int[] list) {
        for (int aList : list) {
            System.out.print(aList + " ");
        }
        System.out.println("");
    }
}

改进了下

package array;

/**
 * @author ethan
 * @date 2019/10/21 09:03
 */
@SuppressWarnings("unchecked")
public class ArrayList<E> {

    /**
     * 元素的数量
     */
    private int size;

    /**
     * 所有元素
     */
    private E[] elements;

    private static final int DEFAULT_CAPACITY = 10;
    private static final int ELEMENT_NOR_FOUND = -1;

    public ArrayList(int size) {
        if (size <= 0) {
            size = DEFAULT_CAPACITY;
        }
        elements = (E[])new Object[size];
    }

    public ArrayList() {
        this(DEFAULT_CAPACITY);
    }

    public int size() {
        return size;
    }


    public boolean isEmpty() {
        return size == 0;
    }

    public boolean contains(E element) {
        int i = indexOf(element);
        if (i == ELEMENT_NOR_FOUND) {
            return false;
        }
        return true;
    }

    public int indexOf(E element) {
        if (element == null) {
            for (int i = 0; i < size; i++) {
                if (elements[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = 0; i < size; i++) {
                if (element.equals(elements[i])) {
                    return i;
                }
            }
        }
        return ELEMENT_NOR_FOUND;
    }

    public E get(int index) {
        rangeCheck(index);
        return elements[index];
    }

    public E set(int index, E element) {

        rangeCheck(index);

        E old = elements[index];
        elements[index] = element;
        return old;
    }

    public void add(E element) {
        add(size, element);
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacity(size + 1, elements.length);

        for (int i = size; i > index; i--) {
            elements[i] = elements[i-1];
        }
        elements[index] = element;
        size++;
    }

    private void ensureCapacity(int size, int length) {
        if (size > length) {
            E[] newElements = (E[]) new Object[length + (length >> 1)];
            for (int i = 0; i < size - 1; i++) {
                newElements[i] = elements[i];
            }
            elements = newElements;
        }
    }

    public E remove(int index) {
        rangeCheck(index);
        E old = elements[index];
        for (int i = index + 1; i <= size - 1; i++) {
            elements[i - 1] = elements[i];
        }
        elements[--size] = null;

        return old;
    }

    public void clear() {
        for (int i = 0; i < size; i++) {
            elements[i] = null;
        }
        size = 0;
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("index=" + index +", size=" + size);
        }
    }

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("index=" + index +", size=" + size);
        }
    }

    @Override
    public String toString() {

        StringBuilder builder = new StringBuilder();
        builder.append("size=").append(size).append(", [");
        for (int i = 0; i < size; i++) {
            builder.append(elements[i]);
            if (i != size -1) {
                builder.append(", ");
            }
        }
        builder.append("]");
        return builder.toString();
    }
}

上一篇下一篇

猜你喜欢

热点阅读