1. 程式人生 > 實用技巧 >25java模擬容器的實現

25java模擬容器的實現

模擬ArrayList容器的實現

實現一個容器,能夠存放任意型別的資料,能夠自動擴容,能夠實現一系列方法。

下面是練習容器的程式的第一個版本:

package MyArrayListSimulation;

public class MyArrayList {
    private Object[] value;//建立一個Object類的陣列物件,所有的類都是Object類的子類,所以這個陣列能夠儲存所有型別物件
    private int size;//建立一個變數儲存陣列的長度
    private int newCapacity;

    public MyArrayList() {//無參構造器
//        value = new Object[16];//預設長度是16
        this(16);
    }

    public MyArrayList(int size) {//有參構造器
        value = new Object[size];//建立指定長度的Object類的陣列物件
    }

    public void add(Object object) {//向容器中新增成分
        value[size] = object;
        size++;
        if (size >= 16) {
            newCapacity = size * 2 + 2;
            Object[] newValue = new Object[newCapacity];
            for (int i = 0; i < value.length; i++) {
                newValue[i] = value[i];
            }
            value = newValue;
        }
    }

    public int getNewCapacity() {
        return newCapacity;
    }

    public int getSize() {//獲取容器當前大小
        return size;
    }

    public Object getValue(int index) {
        return value[index];
    }

    public static void main(String[] args) {
        MyArrayList myArrayList = new MyArrayList();
        myArrayList.add("ffd");
        myArrayList.add("~!@#$%^&*()");
        myArrayList.add("#");
        myArrayList.add("^*fd*^");
        myArrayList.add(new Human("賓士", 1));
        for (int i = 0; i < myArrayList.getSize(); i++) {
            if (i == myArrayList.getSize() - 1) {
                Human human = (Human) myArrayList.getValue(i);
                System.out.println(human.name + "\t" + human.age);
            } else {
                System.out.println(myArrayList.getValue(i));
            }
        }
        System.out.println("Now the ArrayList have "+myArrayList.getSize()+" babys");
        int realCapacity = myArrayList.getSize()<myArrayList.getNewCapacity()?																		     myArrayList.getNewCapacity():16;
        System.out.println("Now the ArrayList's capacity is "+realCapacity);
    }
}
package MyArrayListSimulation;

public class Human {
    public String name;
    public int age;

    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

執行結果:

分析:容器的初始大小設為16,總共向容器中輸入了5個不同型別的物件,經測試能夠正常輸出。

但是我在測試連續向容器中放入超過初試大小(16)的物件個數時,比如放入了18個物件,那麼此時容器會自動擴容一次,根據規則擴容一次之後的大小應該為16*2+2=34,但是實際輸出的容器大小卻是38,這是為什麼?

初步判斷問題是出現在擴容的時候,所以我在擴容操作處設定了一個斷點,然後進行debug,如下圖:

當新增第16個物件時,size=15,然後size++,滿足if語句條件,進入擴容操作,如上圖所示,在執行完newCapacity = size * 2 + 2;後新的容器容量確實變成了16*2+2=34,然後把之前容器中的元素全部複製到新的容器中,到這裡都沒有問題,那麼當呼叫add方法新增第17個物件時,size=16,size++之後仍滿足if條件語句,又會執行擴容程式擴容一次,實際上此時並未溢位,接下來的幾個元素也是會這樣執行,當新增第18個物件時,size=18,newCapacity=18 x 2 + 2 =38,此時已經找到了問題的根源,解決辦法也很簡單,只需要在執行擴容語句的if條件語句多加一個判斷條件即可,即:if ((size >= 16)&&(size>=newCapacity))

,輸出結果如下:


上面雖然基本實現了容器的功能,但是程式不夠健壯,比如沒有校驗索引是否越界?下面進行完善並新增查詢獲取並返回容器中物件的索引位置、替換特定索引的物件等。

第二個版本如下:

package MyArrayListSimulation;

public class MyArrayList {
    private Object[] value;//建立一個Object類的陣列物件,所有的類都是Object類的子類,所以這個陣列能夠儲存所有型別物件
    private int size;//建立一個變數儲存陣列的長度
    private int newCapacity;

    public MyArrayList() {//無參構造器
//        value = new Object[16];//預設長度是16
        this(16);
    }

    public MyArrayList(int size) {//有參構造器
        if (size < 0) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        value = new Object[size];//建立指定長度的Object類的陣列物件
    }

    public void add(Object object) {//向容器中新增成分
        value[size] = object;
        size++;
        if ((size >= 16) && (size >= newCapacity)) {
            newCapacity = size * 2 + 2;
            Object[] newValue = new Object[newCapacity];
            for (int i = 0; i < value.length; i++) {
                newValue[i] = value[i];
            }
            value = newValue;
        }
    }

    public int getNewCapacity() {
        return newCapacity;
    }

    public int getSize() {//獲取容器當前大小
        return size;
    }

    public Object getValue(int index) {
        if (index < 0 || index > size - 1) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return value[index];
    }

    public int getIndex(Object object) {//獲取特定物件索引
        if (object == null) {
            return -1;
        } else {
            for (int i = 0; i < value.length; i++) {
                if (value[i] == object)
                    return i;
            }
        }
        return -1;
    }

    public Object getObject(int index) {//獲取索引位置的物件
        if (index < 0 || index > size - 1) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return value[index];
    }

    public void replaceObject(int index, Object object) {
        if (index < 0 || index > size - 1) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            value[index] = object;
        }
    }

    public void outputArrayList() {
        for (int i = 0; i < getSize(); i++) {
            if (i == getSize() - 1) {
                Human human = (Human) getValue(i);
                System.out.println(human.name + "\t" + human.age);
            } else {
                System.out.println(getValue(i));
            }
        }
    }

    public static void main(String[] args) {
        MyArrayList myArrayList = new MyArrayList();
        myArrayList.add("ffd");
        myArrayList.add("~!@#$%^&*()");
        myArrayList.add("#");
        myArrayList.add("^*fd*^");
        myArrayList.add(new Human("賓士", 1));
        myArrayList.outputArrayList();
        System.out.println("Now the ArrayList have " + myArrayList.getSize() + " babys");
        int realCapacity = myArrayList.getSize() < myArrayList.getNewCapacity() ? 																	   myArrayList.getNewCapacity() : 16;
        System.out.println("Now the ArrayList's capacity is " + realCapacity);
        myArrayList.replaceObject(2, "12345");
        System.out.println("The String (^*fd*^)'s index is: " + myArrayList.getIndex("ffd"));
        System.out.println("The index of object is: " + myArrayList.getObject(1));
        myArrayList.outputArrayList();
    }
}

執行結果:

基本實現功能,當然還有很多待優化的內容,以後我再繼續完善。