JAVA隨時筆記(三):自己實現一個簡單的ArrayList

        本着更加深刻的理解ArrayList的目的,所以自己實現一個簡單的ArrayList,只是實現了List接口,實現了大部分的方法,其實還有一些地方不完善,比如對於參數的異常判斷,返回值的判斷,還有常數的直接使用。其實只要明白其中的原理即可。

MyArrayList類:

package testpackge.util;

import java.util.*;

/**
 * 自己實現ArrayList有,實現List接口,實現大部分方法
 *
 * @Authoc: Alic(1071631279 @ qq.com)
 * @creattime: 2018/5/420:11
 */
public class MyArrayList<E> implements List<E>{

    /**
     * MArrayList內部實際是一個object數組,初始化默認是一個空的數組
     */
    private Object[] elementData = {};
    /**
     * 集合中數據的個數
     */
    private int size;

    /**
     * 默認空參構造
     */
    public MyArrayList(){

    }

    /**
     *有參構造
     * @param capacity  初始化容量
     */
    public MyArrayList(int capacity){
        this.elementData = new Object[capacity];
    }

    /**
     * 集合作爲構造參數
     * @param c 初始化加入的集合
     */
    public MyArrayList(Collection<? extends E> c){
        this.elementData = c.toArray();
        this.size = c.size();
    }


    /**
     * 添加元素,默認添加到末尾
     * @param e  添加的元素
     * @return   返回false
     */
    public boolean add(E e) {
        //擴容方法
        grow(size+1);
        //把元素添加到元素的末尾
        elementData[size++] = e;
        return true;
    }


    /**
     * 在指定位置添加元素
     * @param index   指定索引位置
     * @param element   添加的元素
     */
    public void add(int index, E element) {
        //越界檢查
        if(index>size||index<0){
            throw new RuntimeException("ArrayIndexOutOfBoundsException");
        }
        //擴容
        grow(size+1);
        //把elementData的index及後面的size-index個元素複製到elementData的index+1開始的位置上
        System.arraycopy(elementData,index,elementData,index+1,size-index);
        //index賦值element
        elementData[index] = element;
        //size增加
        size++;
    }

    /**
     * 添加一個集合
     * @param c  添加的集合
     * @return   返回false
     */
    public boolean addAll(Collection<? extends E> c) {
        //轉換爲數組
        Object[] objects = c.toArray();
        //數組長度
        int num = objects.length;
        //擴容操作
        grow(size+num);
        //把objects的0開始的num個元素複製到elementData的size開始的位置上
        System.arraycopy(objects, 0, elementData, size, num);
        //更改size的值
        size += num;
        return true;
    }


    /**
     * 指定位置添加一個集合
     * @param index   指定位置索引
     * @param c       添加的集合
     * @return        返回true
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        //越界檢查
        if(index>size||index<0){
            throw new RuntimeException("ArrayIndexOutOfBoundsException");
        }
        //轉換爲數組
        Object[] objects = c.toArray();
        //數組的長度
        int num = objects.length;
        //擴容
        grow(size+num);

        //把elementData的index開始的size-index個元素複製到elementData的index+num開始的位置上
        System.arraycopy(elementData,index, elementData, index+num, size-index);
        //把objects的0開始的num個元素複製到elementData的index開始的位置上
        System.arraycopy(objects,0, elementData, index, num);
        //更新size的值
        size += num;
        return true;
    }


    /**
     * 擴容方法
     * @param capacity  需要的最小容量值
     */
    private void  grow(int capacity){
        //集合目前的容量
        int oldcapacity = elementData.length;
        //如果集合初始化爲添加任何元素,空的數組
        if(oldcapacity==0){
            //默認容量10
            elementData = new Object[10];
        }else {
            //把容量擴大至原來的1.5倍
            while (capacity < oldcapacity) {
                //把elementData的數據複製到capacity大小的新數組中並且返回,
                elementData = Arrays.copyOf(elementData, capacity = oldcapacity + oldcapacity >> 1);
            }
        }
    }


    /**
     * 移除o元素
     * @param o  刪除元素
     * @return   找到刪除返回true,否則返回false
     */
    public boolean remove(Object o) {

        //獲取索引位置
        int indexOf = indexOf(o);
        if(indexOf>=0){
            //刪除索引indexOf的元素
            remove(indexOf);
            return true;
        }
        return false;
    }

    /**
     * 刪除index的元素
     * @param index  索引位置
     * @return   返回對應元素
     */
    public E remove(int index) {
        //越界檢查
        if(index>size||index<0){
            throw new RuntimeException("ArrayIndexOutOfBoundsException");
        }
        E e = (E)elementData[index];
        //把elementData的index+1開始的size-index-1個元素複製到elementData的index開始的位置上
        System.arraycopy(elementData,index+1,elementData,index,size-index-1);
        //把最後一個元素置爲null,便於GC,size更新
        elementData[size--] = null;
        return e;
    }

    /**
     * 移除c的全部集合
     * @param c  集合對象
     * @return   返回true
     */
    public boolean removeAll(Collection<?> c) {
        //迭代器迭代刪除
        Iterator<?> iterator = c.iterator();
        while(iterator.hasNext()){
            Object next = iterator.next();
            remove(next);
        }
        return true;
    }

    /**
     * 獲取o對應的索引
     * @param o   查找的對象
     * @return    返回對應索引位置,找到就返回
     */
    public int indexOf(Object o) {
        //如果是null值,循環遍歷判斷有無null值
        if(o==null){
            for(int i = 0;i<size;i++){
                if(elementData[i]==null){
                    return i;
                }
            }
        }else{
            //循環遍歷判斷,使用equals判斷是否相等
            for(int i = 0;i<size;i++){
                if(o.equals(elementData[i])){
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 獲取集合中最後一個o值
     * @param o  獲取o相等的值
     * @return  返回對應的索引位置
     */
    public int lastIndexOf(Object o) {
        //循環從後向前白遍歷
        if(o==null){
            for(int i = size-1;i>=0;i--){
                if(elementData[i]==null){
                    return i;
                }
            }
        }else{
            for(int i = size-1;i>=0;i--){
                if(o.equals(elementData[i])){
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 獲取size的值
     * @return  返回size值
     */
    public int size() {
        return size;
    }

    /**
     * 判斷是否爲空,即判斷size是否爲0
     * @return  爲空返回true,否則返回false
     */
    public boolean isEmpty() {
        return size==0;
    }

    /**
     * 判斷是否包含o值,如果indexOf返回-1就沒有對應的值
     * @param o  判斷包含的值
     * @return   包含就返回true,否則返回false
     */
    public boolean contains(Object o) {
        return indexOf(o)>=0;
    }


    /**
     * 是否包含c中所有的值
     * @param c  判斷的集合對象
     * @return  全部包含返回true,否則返回false
     */
    public boolean containsAll(Collection<?> c) {

        //迭代判斷,有一個不是就返回false
        Iterator<?> iterator = c.iterator();
        while(iterator.hasNext()){
            Object next = iterator.next();
            if(indexOf(next)<0){
                return false;
            }
        }
        return true;
    }


    /**
     * 清除集合元素
     */
    public void clear() {
        //循環遍歷置爲null.便於GC
        for(int i = size-1;i>=0;i--){
            elementData[i]=null;
        }
        //更改size爲0
        size = 0;
    }

    /**
     * 獲取index所有上的值
     * @param index
     * @return  返回對應的元素
     */
    public E get(int index) {
        //越界檢查
        if(index>size||index<0){
            throw new RuntimeException("ArrayIndexOutOfBoundsException");
        }
        return (E)elementData[index];
    }


    /**
     * 更新index上的值爲element
     * @param index
     * @param element
     * @return  返回index舊的值
     */
    public E set(int index, E element) {
        //越界檢查
        if(index>size||index<0){
            throw new RuntimeException("ArrayIndexOutOfBoundsException");
        }
        //index的原始值
        E e = (E)elementData[index];
        //更改index的引用爲element
        elementData[index] = element;
        return e;
    }

    /**
     * 轉換爲數組
     * @return   返回數組
     */
    public Object[] toArray() {
        //創建一個長度爲size的數組,循環遍歷賦值
        Object[] objects = new Object[size];
        for(int i = 0;i<size;i++){
            objects[i]=elementData[i];
        }
        return objects;
    }

    /**
     * 截取formIndex到toIndex的值的集合,包含左右邊界
     * @param fromIndex  起始值
     * @param toIndex    結束值
     * @return   返回截取的集合
     */
    public List<E> subList(int fromIndex, int toIndex) {
        //越界檢查,已經確保fromIndex小於等於toIndex
        if(fromIndex>size||fromIndex<0||toIndex>size||toIndex<0||fromIndex>toIndex){
            throw new RuntimeException("ArrayIndexOutOfBoundsException");
        }
        //創建新的對象
        MyArrayList<E> myArrayList = new MyArrayList();
        //創建toIndex-fromIndex+1長度的數組
        Object[] objects = new Object[toIndex-fromIndex+1];
        //遍歷賦值
        for(int i = fromIndex;i<=toIndex;i++){
            objects[i]=elementData[i];
        }
        //設置size值
        myArrayList.size = toIndex-fromIndex+1;
        //設置集合的元素數組
        myArrayList.elementData = objects;
        return myArrayList;
    }


    /**
     * 重寫toString方法
     * @return  返回集合數據的字符串
     */
    @Override
    public String toString() {
        //創建stringBuder對象
        StringBuilder stringBuilder = new StringBuilder();
        //遍歷拼接字符串,每一個對象加一個","
        stringBuilder.append("[");
        for(int i = 0;i<size;i++){
            stringBuilder.append(((E)elementData[i]).toString());
            stringBuilder.append(",");
        }

        //清除最後一個","字符
        int lastIndexOf = stringBuilder.lastIndexOf(",");
        if(lastIndexOf>0){
            stringBuilder.deleteCharAt(lastIndexOf);
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }

    /**
     * 迭代器對象
     */
    public class Itr implements Iterator<E>{
        /**
         * 迭代到的索引位置
         */
        private int cursor;

        /**
         * 是否還有下一個元素,即判斷迭代位置是否已到size
         * @return 還有返回true,沒有返回false
         */
        @Override
        public boolean hasNext() {
            return cursor!=size;
        }

        /**
         * 返回下一個元素,直接返回elementData的對應數據
         * @return 返回對應元素
         */
        @Override
        public E next() {
            return (E)elementData[cursor++];
        }
    }

    /**
     * 返回迭代器對象,創建一個內部類
     * @return  內部類迭代器對象
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

   //下面的方法其實都是一樣的,只要明白了其中的原理即可,以下四個方法不實現了

    public ListIterator<E> listIterator() {
        return null;
    }

    public ListIterator<E> listIterator(int index) {
        return null;
    }

    public boolean retainAll(Collection<?> c) {
        return false;
    }

    public <T> T[] toArray(T[] a) {
        return null;
    }
}

Main測試代碼:

MyArrayList<ClassA> myArrayList = new MyArrayList();
ClassA a1 = new ClassA(12,"a1");
ClassA a2 = new ClassA(13,"a2");
ClassA a3 = new ClassA(14,"a3");
ClassA a4 = new ClassA(15,"a4");

System.out.println("------初始化後------");
System.out.println("size:"+myArrayList.size());

System.out.println("------開始添加元素------");
myArrayList.add(a1);
System.out.println(myArrayList);

System.out.println("contrins方法,是否包含a1:"+myArrayList.contains(a1));
System.out.println("size:" + myArrayList.size());

System.out.println("在1位置添加一個元素a2");
myArrayList.add(1,a2);
System.out.println(myArrayList);
System.out.println("size:" + myArrayList.size());
System.out.println("在2位置添加一個元素a3");
myArrayList.add(2,a3);
System.out.println(myArrayList);
System.out.println("size:" + myArrayList.size());

System.out.println("獲取2位置上的元素:"+myArrayList.get(2));


System.out.println("獲取a1元素的索引位置:" + myArrayList.indexOf(a1));

System.out.println("判斷集合是否爲空:" + myArrayList.isEmpty());

System.out.println("移除索引爲1的元素:");
myArrayList.remove(1);
System.out.println(myArrayList);
System.out.println("size:" + myArrayList.size());
System.out.println("移除a3:");
myArrayList.remove(a3);
System.out.println(myArrayList);
System.out.println("size:" + myArrayList.size());

System.out.println("添加a2元素");
myArrayList.add(a2);
System.out.println(myArrayList);
System.out.println("size:" + myArrayList.size());
System.out.println("更新索引1位置的元素爲a4");
myArrayList.set(1,a4);
System.out.println(myArrayList);
System.out.println("添加a3元素");
myArrayList.add(a3);
System.out.println(myArrayList);
System.out.println("size:" + myArrayList.size());

System.out.println("截取索引爲0-2的元素,得到subList:");
List<ClassA> subList = myArrayList.subList(0, 2);
System.out.println(subList);

System.out.println("clear方法清空subList:");
subList.clear();
System.out.println(subList);

System.out.println("toArray方法得到數組:");
Object[] objects = myArrayList.toArray();
for (int i = 0,len = myArrayList.size();i<len;i++){
    System.out.println(myArrayList.get(i));
}

System.out.println("迭代器測試:");
Iterator<ClassA> iterator = myArrayList.iterator();
while (iterator.hasNext()){
    System.out.println(iterator.next());
}

System.out.println("有參構造得到arrayList");
MyArrayList arrayList = new MyArrayList(myArrayList);

System.out.println(arrayList);


輸出結果:

------初始化後------
size:0
------開始添加元素------
[ClassA{age=12, name='a1'}]
contrins方法,是否包含a1:true
size:1
在1位置添加一個元素a2
[ClassA{age=12, name='a1'},ClassA{age=13, name='a2'}]
size:2
在2位置添加一個元素a3
[ClassA{age=12, name='a1'},ClassA{age=13, name='a2'},ClassA{age=14, name='a3'}]
size:3
獲取2位置上的元素:ClassA{age=14, name='a3'}
獲取a1元素的索引位置:0
判斷集合是否爲空:false
移除索引爲1的元素:
[ClassA{age=12, name='a1'},ClassA{age=14, name='a3'}]
size:2
移除a3:
[ClassA{age=12, name='a1'}]
size:1
添加a2元素
[ClassA{age=12, name='a1'},ClassA{age=13, name='a2'}]
size:2
更新索引1位置的元素爲a4
[ClassA{age=12, name='a1'},ClassA{age=15, name='a4'}]
添加a3元素
[ClassA{age=12, name='a1'},ClassA{age=15, name='a4'},ClassA{age=14, name='a3'}]
size:3
截取索引爲0-2的元素,得到subList:
[ClassA{age=12, name='a1'},ClassA{age=15, name='a4'},ClassA{age=14, name='a3'}]
clear方法清空subList:
[]
toArray方法得到數組:
ClassA{age=12, name='a1'}
ClassA{age=15, name='a4'}
ClassA{age=14, name='a3'}
迭代器測試:
ClassA{age=12, name='a1'}
ClassA{age=15, name='a4'}
ClassA{age=14, name='a3'}
有參構造得到arrayList
[ClassA{age=12, name='a1'},ClassA{age=15, name='a4'},ClassA{age=14, name='a3'}]

發佈了43 篇原創文章 · 獲贊 38 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章