1. 程式人生 > >Java容器之ArrayList原始碼總結

Java容器之ArrayList原始碼總結

Java容器之ArrayList原始碼總結

本次學習基於JDK1.7版本,目的在於對常用的容器類進行深入學習,加深理解,以便工作中更好的使用。

容器基本概念

Java容器類類庫的用途是“儲存物件”,並劃分為兩個不同的概念:
1、Collection儲存單一的元素。
2、Map儲存相關聯的鍵值對。
容器不能持有基本型別(8種),但自動包裝機制會執行基本型別到容器中所持有的包裝器型別之間的雙向轉換。

自定義介面及對應的實現類

以下所有自定義類參考原始碼並做了一定處理,保留下重要的部分,用於參考理解容器內部的資料結構和功能實現,但是在完整性和嚴謹性上有所欠缺。

迭代器Iterator

Iterable介面中持有Iterator迭代器

package gemme.collection;
/**
 * 自定義的Iterable介面
 * */
public interface IMyIterable<T>  {

    IMyIterator<T> myIterator();
}

迭代器是一個物件,它的工作是遍歷並選擇序列中的物件,同時它也被稱為“輕量級物件”,建立它的代價小。Iterator只能單向移動。

package gemme.collection;
/**
 * 自定義迭代器
 * */
public interface IMyIterator<E> {
    // 下一個元素是否存在
    boolean hasNext();
    // 獲取下一個元素
    E next();
    // 移除本元素
    void remove();
}

Iterator的真正威力在於能夠將遍歷序列的操作與序列底層的結構分離。迭代器統一了對容器的訪問方式。

介面Collection和抽象類AbstractCollection

自定義IMyCollection介面仿照java.util.Collention介面,MyAbstractCollection抽象類仿照java.util.AbstractCollection類,均只實現了部分重要的方法,具體請參考原始碼。其中迭代器用Java.util.Iterator,如果用自定義的迭代器IMyIterator會在foreach迴圈中報錯,提示iterator方法沒實現。

package gemme.collection;

import java.util.Iterator;

/**
 * 自定義集合Collection
 * */
public interface IMyCollection<E> extends Iterable<E> {
    // 集合內元素個數
    int size();
    
    // 迭代器
    @Override
    Iterator<E> iterator();
    
    // 新增一個元素
    boolean add(E element);
    
    // 刪除一個元素
    boolean remove(Object o);
    
    // 是否包含該元素
    boolean contains(Object o);
}

抽象實現類AbstractCollection繼承Collection介面,下面是自定義的抽象類MyAbstractCollection,

package gemme.collection;

import java.util.Iterator;

public abstract class MyAbstractCollection<E>  implements IMyCollection<E> {

    @Override
    public abstract int size();

    public abstract Iterator<E> iterator();

    @Override
    public abstract boolean add(E element);

    /**
     * 利用迭代器進行刪除
     * */
    @Override
    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o == null) {
            while (it.hasNext()) {
                if (it.next() == null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (it.next().equals(o)) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }


    @Override
    public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o == null) {
            while (it.hasNext()) {
                if (it.next() == null) {
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (it.next().equals(o)) {
                    return true;
                }
            }
        }
        return false;
    }
}

介面List、抽象類AbstractList和實現類ArrayList

自定義IMyList介面仿照java.util.List介面,MyArrayList類仿照java.util.ArrayList類,抽象類MyAbstractList仿照java.util.AbstractList。MyAbstractList並沒有任何方法或變數,只保留繼承關係。

package gemme.collection;

import java.util.Iterator;

public interface IMyList<E> extends IMyCollection<E> {
    // 集合內元素個數
    @Override
    int size();
    
    // 迭代器
    @Override
    Iterator<E> iterator();
    
    // 新增元素element
    @Override
    boolean add(E element);
    
    // 在指定位置index,新增元素element
    void add(int index, E element);
    
    // 移除元素o
    @Override
    boolean remove(Object o);
    
    // 移除元素並返回該元素
    E remove(int index);
    
    // 集合中是否包含元素o
    @Override
    boolean contains(Object o);
    
    // 獲取指定位置index下的元素
    E get(int index);
    
    // 設定指定位置index下的元素為element
    E set(int index, E element);
}

package gemme.collection;
/**
 * 自定義抽象類AbstractList,保留繼承關係,不具體實現
 * */
public abstract class MyAbstractList<E> extends MyAbstractCollection<E>
        implements IMyList<E> {

}
package gemme.collection;

import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class MyArrayList<E> extends MyAbstractList<E> implements IMyList<E> {
    // 元素數目
    private int size;

    // 元素儲存區間
    private Object[] elementData;

    // 預設初始陣列長度
    private static final int DEFAULT_CAPACITY = 10;

    public MyArrayList() {
        elementData = new Object[DEFAULT_CAPACITY];
        size = 0;
    }

    @Override
    public E get(int index) {
        rangeCheck(index);
        return (E) elementData[index];
    }

    @Override
    public E set(int index, E element) {
        rangeCheck(index);
        Object oldElement = elementData[index];
        elementData[index] = element;
        return (E) oldElement;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean add(E element) {
        ensureCapacityInternal(size + 1);
        elementData[size++] = element;
        return true;
    }

    @Override
    public void add(int index, E element) {
        rangeCheckForAdd(index);
        ensureCapacityInternal(size + 1);
        // 當插入陣列中間位置時,陣列整體向後移一位
        System.arraycopy(elementData, index, elementData,
                index + 1, size - index);
        elementData[index] = element;
        size++;
    }

    @Override
    public E remove(int index) {
        rangeCheckForAdd(index);
        E oldElement = (E) elementData[index];
        int numMoved = size - index - 1;
        if (numMoved > 0) {
        	// 從列表中間刪除時,元素整體向前移動一位
            System.arraycopy(elementData, index + 1, elementData,
                    index, numMoved);
        }
        // 釋放記憶體空間便於GC回收
        elementData[--size] = null;
        return oldElement;
    }

    private void rangeCheck(int index) {
        if (index >= size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
    }

    private void ensureCapacityInternal(int minCapacity) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        if (minCapacity > elementData.length) {
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    }

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


    @Override
    public Iterator<E> iterator() {
        return new MyItr();
    }

    /**
     * 內部迭代器實現,在原始碼基礎上做了簡化,保留下主要功能和邏輯,具體請參考JDK1.7原始碼
     * */
    private class MyItr<E> implements Iterator<E> {

        int cursor = 0;

        int lastRet = -1;

        @Override
        public boolean hasNext() {
            return cursor != size;
        }

        @Override
        public E next() {
            int i = cursor;
            if (i >= size) {
                throw new NoSuchElementException();
            }
//            Object[] elementArray = elementData;
            Object[] elementArray = MyArrayList.this.elementData;
            cursor = i + 1;

            return (E) elementArray[lastRet = i];
        }

        @Override
        public void remove() {
            if (lastRet < 0) {
                throw new IllegalStateException();
            }
            MyArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
        }
    }
}

驗證部分留給觀眾老爺自己啦,我自測了沒有發現bug,大家有什麼建議或者發現什麼問題請留言啦。