數據結構學習-動態數組

學習數據結構 -動態數組 模仿 ArrayList

public class ArrayList<E> {
    /**
     * 大小
     */
    private int size;

    /**
     * 原始數組
     */
    private Object[] elementData;
    /**
     * 空數組
     */
    private static final Object[] EMPTY_DATA = {};
    /**
     * 默認數組長度
     */
    private static final int DEFAULT_CAPACITY = 10;


    public ArrayList(int initialCapacity) {
        // 大於0 設置爲用戶大小  等於0 給空數組  否則設置錯誤
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_DATA;
        } else {
            throw new IllegalArgumentException("長度設置錯誤" + initialCapacity);
        }
    }

    public ArrayList() {
        // 沒設置給個空數組
        this.elementData = EMPTY_DATA;
    }

    public int size() {
        return size;
    }

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

    /**
     * 添加數據
     *
     * @param e 數據
     * @return 添加成功
     */
    public boolean add(Object e) {
        // 確保我的數組長度是當前實際大小+1
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }

    /**
     * 添加方法 帶下標位置
     *
     * @param index 下標
     * @param e     數據
     * @return 添加成功
     */
    public boolean add(int index, Object e) {
        // 校驗位置
        rangeCheckForAdd(index);
        // 確保數組長度我能放進去
        ensureCapacityInternal(size + 1);
        //添加指定位置並移動指定位置後數據  系統方法 複製數組很有趣  可以實現自己複製給自己
        // 比如 0 1 2 3 4 5   我插入下標爲3 的數據 變成 0 1 2 e 3 4 5 意思就是  把源數組 下標爲3起始位置 開始 copy 到目標數組index+1 起始位置後的數據
        // copy長度size-index
        System.arraycopy(elementData, index, elementData, index + 1,
                size - index);
        elementData[index] = e;
        size++;
        return true;
    }

    /**
     * 獲取指定下標數據
     *
     * @param index 下標
     * @return 數據
     */
    public E get(int index) {
        // 驗證下標是否在正常範圍
        rangeCheck(index);
        return (E) elementData[index];
    }

    /**
     * 設置 指定下標數據
     *
     * @param index 下標
     * @param e     修改數據
     */
    public E set(int index, int e) {
        // 驗證下標是否在正常範圍
        rangeCheck(index);
        // 返回舊值
        E oldElementData = (E) elementData[index];
        elementData[index] = e;
        return oldElementData;
    }

    /**
     * 刪除指定下標數據
     *
     * @param index 下標
     * @return 舊數據
     */
    public E remove(int index) {
        // 檢測下標是否越界
        rangeCheck(index);
        //返回舊值
        E oldElementData = (E) elementData[index];
        // 上面index能過檢測 最大的大小就是size -1 就是數組最後一個值的下標
        int move = size - index - 1;
        if (move > 0) {
            // 說明需要移動下標 不是最後一位   比如 我有 1,2,3,4 數組 我要修改 數組爲2下標的數據 我就要移動4 移動到 3 的位置 長度爲 size-2-1
            System.arraycopy(elementData, index + 1, elementData, index, move);
        }
        // 移動過後最後一位需要清空 不然數據不會消失
        elementData[--size] = null;
        return oldElementData;
    }

    /**
     * 返回數據指定下標
     *
     * @param e 數據
     * @return 下標
     */
    public int indexOf(Object e) {
        if (e != null) {
            for (int i = 0; i < size; i++) {
                if (e.equals(elementData[i])) {
                    return i;
                }
            }
        } else {
            return -1;
        }
        return -1;
    }


    @Override
    public String toString() {
        StringJoiner stringJoiner = new StringJoiner(", ", "[", "]");
        for (Object element : elementData) {
            if (element != null) {
                stringJoiner.add(String.valueOf(element));
            }
        }
        return stringJoiner.toString();
    }

    /**
     * 下標長度位置是否合法判斷 添加
     *
     * @param index 下標
     */
    private void rangeCheckForAdd(int index) {
        // 只能添加下邊小於等於 當前list長度的 可以添加等於size下標位置的數據
        if (index > size || index < 0) {
            throw new IndexOutOfBoundsException("index 越界(添加時)" + index);
        }
    }

    /**
     * 驗證下標是否越界 獲取
     *
     * @param index 下標
     */
    private void rangeCheck(int index) {
        // 獲取僅存在的下標
        if (index >= size) {
            throw new IndexOutOfBoundsException("下標越界異常" + index);
        }
    }

    /**
     * 確保容量有多大
     *
     * @param minLength 最小長度
     */
    private void ensureCapacityInternal(int minLength) {
        // 判斷 大小 給予 默認大小
        if (elementData == EMPTY_DATA) {
            //表示是空數組給個默認長度
            minLength = DEFAULT_CAPACITY;
        }
        // 如果 數組長度 已經小於我們需要的最小長度 就擴容
        if (minLength > elementData.length) {
            // 舊長度
            int oldLength = elementData.length;
            // 新長度等於舊長度 的 1.5倍   舊長度+舊長度*0.5
            int newLength = oldLength + (oldLength >> 1);
            Object[] copy = new Object[newLength];
            // 把舊數組 賦值給新數組
            System.arraycopy(elementData, 0, copy, 0,
                    oldLength);
            log.warn("擴容原始長度{},擴容後長度{}", oldLength, newLength);
            elementData = copy;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章