手動實現ArrayList動態陣列

dream_yi發表於2020-11-15

手動實現動態陣列

作者q:2835916127
blog:博主部落格

線性表

資料結構: 計算機儲存組織資料的方式
線性表: 具有n個相同元素的有限序列(n>=0)
a1 -> a2 -> a3 -> a4 -> … -> an
a1: 首節點、(首元素)
an: 尾節點(尾元素)

  • a1是a2的前驅節點
  • a2是a1的後繼節點

常見的線性表:

  1. 陣列
  2. 連結串列
  3. 佇列
  4. 雜湊表(雜湊表)
    ……
  • 陣列是一種順序儲存的線性表,所有元素的記憶體地址是連續的

需要知道的一些

  • 變數名是儲存在棧中的

  • new 出來的物件是儲存在堆中的

  • java中成員變數自動初始化,比如:

    • int初始化為0
    • 物件初始化為null
  • 重寫toString()自定義列印陣列

  • StringBuilder可以拼接字串

Object[] ob = new Object[7];
  • 物件陣列
    • ob -> 棧空間
    • ob[i] -> 堆空間
    • ob[i] 裡並非物件本身,而是物件的引用(即地址)
int [] array = new int[10]{11,22,33};

例項:

背景: 在許多語言開發中陣列都有個致命缺點—陣列一旦建立,容量不可變,然而我們都希望陣列長度可以動態變化
需求 :底層採用陣列 實現動態擴容陣列(ArrayList)
目的:

  1. 體會線性結構
  2. 練習常用演算法
  3. 強化陣列
  4. 練習泛型

面對的問題:

  • 陣列一旦建立,容量不可變
  • 擴容的條件
  • 如何處理空值

動態陣列介面設計

int size(); // 元素的數量boolean isEmpty(); // 是否為空boolean contains(E element); // 是否包含某個元素void add(E element); // 新增元素到最後面
◼ E get(int index); // 返回index位置對應的元素
◼ E set(int index, E element); // 設定index位置的元素void add(int index, E element); // 往index位置新增元素
◼ E remove(int index); // 刪除index位置對應的元素int indexOf(E element); // 檢視元素的位置void clear(); // 清除所有元素

具體實現:

package cn.dreamyi.demo;

/**
 * 動態可變陣列  自動擴容
 * qq:2835916127
 */
public class DynamicArray<E> {
    private int size = 0;//儲存當前元素長度

    //定義預設初始化容量
    private final int DEFAULT_CAPACITY = 10;

    //查詢失敗返回值
    private final int ELEMENT_NOt_FOUND = -1;
    //用於儲存陣列元素
    private E[] elements = (E[]) new Object[DEFAULT_CAPACITY];

    /**
     * 檢查索引越界
     *
     * @param index 當前訪問索引
     */
    private void checkIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引越界" + "允許範圍 size:0 => " + (size - 1) + " 當前索引:" + index);
        }
    }

    /**
     * 檢查新增索引越界
     *
     * @param index 新增位置的索引
     */
    private void checkAddIndex(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("索引越界" + "允許範圍 size:0 => " + (size) + " 當前索引:" + index);
        }
    }

    /**
     * 確保陣列容量夠用
     */
    private void ensureCapacity() {
        //擴容1.5倍
        E[] newElements = (E[]) new Object[elements.length + (elements.length >> 1)];

        for (int i = 0; i < size; i++) {
            newElements[i] = elements[i];
        }
        elements = newElements;//引用
    }

    public DynamicArray() {
    }

    /**
     * 帶參初始化
     *
     * @param capacity 初始化容量
     */
    public DynamicArray(int capacity) {
        if (capacity < 10) {
            elements = (E[]) new Object[DEFAULT_CAPACITY];
        } else {
            elements = (E[]) new Object[capacity];
        }
    }

    /**
     * 返回當前元素的數量
     *
     * @return 當前元素的個數
     */
    public int size() {
        return size;
    }

    /**
     * 當前陣列是否為空
     * 空:true
     * 非空:false
     *
     * @return 返回true | false
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 是否包含某個元素
     *
     * @param element
     * @return 返回true | false
     */
    public boolean contains(E element) {
        if (element == null) {
            for (int i = 0; i < size; i++) {
                if (elements[i] == null) return true;
            }
        } else {
            for (int i = 0; i < size; i++) {
                if (element.equals(elements[i])) return true;
            }
        }
        return false;
    }

    /**
     * 新增元素到尾部
     *
     * @param element 待新增的元素
     */
    public void add(E element) {
        if (size > elements.length - 1) {
            ensureCapacity();
        }
        elements[size++] = element;
    }

    /**
     * 返回對應索引的值 不存在返回-1
     *
     * @param index 元素的索引
     * @return 對應值 | -1
     */
    public E get(int index) {
        checkIndex(index);

        return elements[index];
    }

    /**
     * 設定index位置元素的值
     *
     * @param index   需要設定的位置索引
     * @param element 設定的值
     * @return 返回原先的值
     */
    public E set(int index, E element) {
        checkIndex(index);//檢查索引越界

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

        return old;
    }


    /**
     * 向index位置新增元素
     *
     * @param index   插入位置的索引
     * @param element 插入的元素
     */
    public void add(int index, E element) {
        checkAddIndex(index);//檢查索引越界

        for (int i = size; i > index; i--) {
            elements[i] = elements[i - 1];//把元素右移
        }
        elements[index] = element;
        size++;
    }

    /**
     * 移除index位置元素
     *
     * @param index 被移除元素的索引
     * @return 返回原先值
     */
    public E remove(int index) {
        checkIndex(index);
        E old = elements[index];

        for (int i = index; i < size; i++) {
            elements[i] = elements[i + 1];
        }
        elements[--size] = null;//清空最後一個元素
        return old;
    }

    /**
     * 查詢元素
     *
     * @param element 需要查詢的元素
     * @return 返回該元素索引 | -1
     */
    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_NOt_FOUND;
    }

    /**
     * 清空所有元素
     */
    public void clear() {
        for (int i = 0; i < size; i++) {
            elements[i] = null;
        }
    }

    /**
     * 返回元素集合size:5, [1, 3, 4 ,5 ,7 ]
     *
     * @return
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("size:" + size + " => [");
        for (int i = 0; i < size; i++) {
            if (i != 0) {
                sb.append(" ,");
            }
            sb.append(elements[i]);
        }
        sb.append("]");
        return sb.toString();
    }
}

主函式中呼叫

   public static void main(String[] args) {
//      System.out.println(feb2(45));
        DynamicArray<String> list = new DynamicArray(1);
       list.add("sdas");
       list.add("32143");
        DynamicArray<Student> stuList = new DynamicArray<>();
        Student st1 = new Student("001", "張三", "19");
        Student st2 = new Student("002", "李四", "23");
        Student st3 = new Student("001", "趙六", "25");
        stuList.add(st1);
        stuList.add(null);
        System.out.println(stuList.contains(null));
        System.out.println(stuList.indexOf(null));
        stuList.add(st2);
        stuList.add(st3);


        System.out.println(stuList.toString());
//        System.out.println(list.toString());

總結:見上面

相關文章