1. 程式人生 > >深入學習java原始碼之ArrayList.spliterator()與ArrayList.subList()

深入學習java原始碼之ArrayList.spliterator()與ArrayList.subList()

深入學習java原始碼之ArrayList.spliterator()與ArrayList.subList()

抽象類

面向物件程式設計來說,抽象是它的一大特徵之一。在Java中,可以通過兩種形式來體現OOP的抽象:介面和抽象類。這兩者有太多相似的地方,又有太多不同的地方。

抽象類中含有無具體實現的方法,所以不能用抽象類建立物件。

抽象類就是為了繼承而存在的,如果你定義了一個抽象類,卻不去繼承它,那麼等於白白建立了這個抽象類,因為你不能用它來做任何事情。對於一個父類,如果它的某個方法在父類中實現出來沒有任何意義,必須根據子類的實際需求來進行不同的實現,那麼就可以將這個方法宣告為abstract方法,此時這個類也就成為abstract類了。

  包含抽象方法的類稱為抽象類,但並不意味著抽象類中只能有抽象方法,它和普通類一樣,同樣可以擁有成員變數和普通的成員方法。注意,抽象類和普通類的主要有三點區別:

  1)抽象方法必須為public或者protected(因為如果為private,則不能被子類繼承,子類便無法實現該方法),預設情況下預設為public。

  2)抽象類不能用來建立物件;

  3)如果一個類繼承於一個抽象類,則子類必須實現父類的抽象方法。如果子類沒有實現父類的抽象方法,則必須將子類也定義為為abstract類。

  在其他方面,抽象類和普通的類並沒有區別。
介面,英文稱作interface,在軟體工程中,介面泛指供別人呼叫的方法或者函式。從這裡,我們可以體會到Java語言設計者的初衷,它是對行為的抽象。

介面中可以含有變數和方法。但是要注意,介面中的變數會被隱式地指定為public static final變數(並且只能是public static final變數,用private修飾會報編譯錯誤),而方法會被隱式地指定為public abstract方法且只能是public abstract方法(用其他關鍵字,比如private、protected、static、 final等修飾會報編譯錯誤),並且介面中所有的方法不能有具體的實現,也就是說,介面中的方法必須都是抽象方法。從這裡可以隱約看出介面和抽象類的區別,介面是一種極度抽象的型別,它比抽象類更加“抽象”,並且一般情況下不在介面中定義變數。
要讓一個類遵循某組特地的介面需要使用implements關鍵字,具體格式如下:
允許一個類遵循多個特定的介面。如果一個非抽象類遵循了某個介面,就必須實現該介面中的所有方法。對於遵循某個介面的抽象類,可以不實現該介面中的抽象方法。

抽象類和介面的區別
  1)抽象類可以提供成員方法的實現細節,而介面中只能存在public abstract 方法;

  2)抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是public static final型別的;

  3)介面中不能含有靜態程式碼塊以及靜態方法,而抽象類可以有靜態程式碼塊和靜態方法;

  4)一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。

抽象類作為很多子類的父類,它是一種模板式設計。而介面是一種行為規範,它是一種輻射式設計。
什麼是模板式設計?最簡單例子,大家都用過ppt裡面的模板,如果用模板A設計了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它們的公共部分需要改動,則只需要改動模板A就可以了,不需要重新對ppt B和ppt C進行改動。
而輻射式設計,比如某個電梯都裝了某種報警器,一旦要更新報警器,就必須全部更新。也就是說對於抽象類,如果需要新增新的方法,可以直接在抽象類中新增具體的實現,子類可以不進行變更;而對於介面則不行,如果介面進行了變更,則所有實現這個介面的類都必須進行相應的改動。

網上流傳最廣泛的例子:門和警報的例子:門都有open( )和close( )兩個動作,此時我們可以定義通過抽象類和介面來定義這個抽象概念:

abstract class Door {
    public abstract void open();
    public abstract void close();
}

interface Door {
    public abstract void open();
    public abstract void close();
}

但是現在如果我們需要門具有報警alarm( )的功能,那麼該如何實現?下面提供兩種思路:

  1)將這三個功能都放在抽象類裡面,但是這樣一來所有繼承於這個抽象類的子類都具備了報警功能,但是有的門並不一定具備報警功能;

  2)將這三個功能都放在接口裡面,需要用到報警功能的類就需要實現這個介面中的open( )和close( ),也許這個類根本就不具備open( )和close( )這兩個功能,比如火災報警器。

從這裡可以看出, Door的open() 、close()和alarm()根本就屬於兩個不同範疇內的行為,open()和close()屬於門本身固有的行為特性,而alarm()屬於延伸的附加行為。
因此最好的解決辦法是單獨將報警設計為一個介面,包含alarm()行為,Door設計為單獨的一個抽象類,包含open和close兩種行為。再設計一個報警門繼承Door類和實現Alarm介面。

interface Alram {
    void alarm();
}
 
abstract class Door {
    void open();
    void close();
}
 
class AlarmDoor extends Door implements Alarm {
    void oepn() {
      //....
    }
    void close() {
      //....
    }
    void alarm() {
      //....
    }
}

抽象類的使用

public abstract class AbsOpeWorker{
	protected String[] synSqls = null;
	protected String[] intoSqls = null;
	protected String ruleCode = null;
	
	public abstract String[] initSynSqls();
	
	
	public abstract String[] initIntoSqls();
	
	public abstract String initRuleCode();
	
	public abstract void synData();
}

抽象類繼承抽象類並且實現裡面的方法

public abstract class AbsOpeByTimeWorker extends AbsOpeWorker{

	protected PrSynRule prSynRule = null;
	protected Date startDate = null;
	protected Date endDate = null;
	public void init() {
		this.ruleCode = initRuleCode();
		this.synSqls = initSynSqls();
		this.intoSqls = initIntoSqls();
	}
	@Override
	public String[] initSynSqls() {
		List<PrSynRule> ruleList = prSynRuleService.querySynRuleList(prSynRule);
		if(ruleList!=null && ruleList.size()>0){
			prSynRule = ruleList.get(0);
			startDate = startTime();
		}
		return new String[]{prSynRule.getContent()};
	}
	
	public abstract Date startTime();
	
	public abstract Date endTime();
	
	@Override
	public String[] initIntoSqls() {
		return null;
	}
	@Override
	public void synData() {
		String startTime = prSynRule.getPointer();
		endDate = endTime();
		this.init();
    }
	@Override
	public String initRuleCode() {
		String ruleCode = setRuleCode();//"";
		if(prSynRule==null){
			prSynRule = new PrSynRule();
		}
		prSynRule.setRuleCode(ruleCode);
		return ruleCode;
	}
	public abstract String setRuleCode();
	
	public abstract int insertObject(List<Object> t);
	
	public abstract Class<?> getEntityClass();
}

繼承抽象類並調通過this和super用抽象類中的方法

public class PipOperationWorker extends AbsOpeByTimeWorker{

	public PipOperationWorker(String ruleCode) {
		this.ruleCode = ruleCode;
	}
	private String ruleCode = "";
	private int insertCount = 8000;
	
	@Override
	public int insertObject(List<Object> t) {
	
	}
	@Override
	public String setRuleCode() {
		return ruleCode;
	}
	@Override
	public Date startTime() {
		return DateUtil.parse(prSynRule.getPointer(), "yyyy-MM-dd HH:mm:ss", null);
	}
	@Override
	public void synData() {
		this.init();
		if("1".equals(prSynRule.getType())){
			super.synData();
		}else if("2".equals(prSynRule.getType())){
			new PipType2Worker(prSynRule.getRuleCode()).synData();
		}else if("3".equals(prSynRule.getType()))
		{
			new PipType3Worker(prSynRule.getRuleCode()).synData();
		}
	}
	@Override
	public Date endTime() {
		Date now = new Date();
		String lastTime = "";
		if(prSynRule!=null && !StringUtil.isEmpty(prSynRule.getPointer())){
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(startDate);
			if(prSynRule.getTimeInterval()==1){
				calendar.add(Calendar.DAY_OF_MONTH, 1);
			}else if(prSynRule.getTimeInterval()==2){
				calendar.add(Calendar.MONTH, 1);
			}else if(prSynRule.getTimeInterval()==4){
				calendar.add(Calendar.YEAR, 1);
			}else if(prSynRule.getTimeInterval() == 5 && "1".equals(prSynRule.getIsOldData())) {
				calendar.add(Calendar.HOUR, 1);
				SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
				now = DateUtil.parse(df.format(calendar.getTime()), "yyyy-MM-dd HH:mm:ss", null);
				return now;
			}
			lastTime = calendar.get(Calendar.YEAR)+"-"+(calendar.get(Calendar.MONTH)+1)+"-"+calendar.get(Calendar.DAY_OF_MONTH);
			lastTime = lastTime+ " 00:00:00";
			now = DateUtil.parse(lastTime, "yyyy-MM-dd HH:mm:ss", null);
		}
		if(prSynRule!=null && !"1".equals(prSynRule.getIsOldData())) {
			now = new Date();
		}
		return now;
	}
	@Override
	public Class<?> getEntityClass() {
		Class<?> _class = null;
		try {
			_class = Class.forName(prSynRule.getModeClass());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			logger.error(MessageFormat.format("====sys worker {0} create ModeClass exception====", ruleCode),e);
		}
		return _class;
	}
	public PipOperationWorker setRuleCode(String ruleCode) {
		this.ruleCode = ruleCode;
		return this;
	}
}

呼叫方法

new PipOperationWorker("pr_data").synData();

 

介面的實現

ArrayList.spliterator()與ArrayList.subList()

Modifier and Type Method and Description
void forEach(Consumer<? super E> action)

Iterable的每個元素執行給定的操作,直到所有元素都被處理或動作引發異常。

Spliterator<E> spliterator()

在此列表中的元素上建立late-binding故障快速 Spliterator

List<E> subList(int fromIndex, int toIndex)

返回此列表中指定的 fromIndex (包括)和 toIndex之間的獨佔檢視。

用於遍歷和分割源的元素的物件。 Spliterator涵蓋的元素的來源可以是例如陣列, Collection ,IO通道或生成器函式。 
分割器可以逐個遍歷元素( tryAdvance() )或批量( forEachRemaining() )。 

分割器也可以將其某些元素(使用trySplit() ) 分割為另一個分割器,以在可能的並行操作中使用。 使用不能分割的Spliter的操作或者以非常不平衡或低效的方式進行的操作不太可能受益於並行性。 穿透和分流排氣元件; 每個Spliterator僅對單個批量計算有用。 

java原始碼

package java.util;

import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    private static final int DEFAULT_CAPACITY = 10;

    private static final Object[] EMPTY_ELEMENTDATA = {};

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    transient Object[] elementData; // non-private to simplify nested class access

    private int size;

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > size)
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
    }

    private class SubList extends AbstractList<E> implements RandomAccess {
        private final AbstractList<E> parent;
        private final int parentOffset;
        private final int offset;
        int size;

        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) {
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = ArrayList.this.modCount;
        }

        public E set(int index, E e) {
            rangeCheck(index);
            checkForComodification();
            E oldValue = ArrayList.this.elementData(offset + index);
            ArrayList.this.elementData[offset + index] = e;
            return oldValue;
        }

        public E get(int index) {
            rangeCheck(index);
            checkForComodification();
            return ArrayList.this.elementData(offset + index);
        }

        public int size() {
            checkForComodification();
            return this.size;
        }

        public void add(int index, E e) {
            rangeCheckForAdd(index);
            checkForComodification();
            parent.add(parentOffset + index, e);
            this.modCount = parent.modCount;
            this.size++;
        }

        public E remove(int index) {
            rangeCheck(index);
            checkForComodification();
            E result = parent.remove(parentOffset + index);
            this.modCount = parent.modCount;
            this.size--;
            return result;
        }

        protected void removeRange(int fromIndex, int toIndex) {
            checkForComodification();
            parent.removeRange(parentOffset + fromIndex,
                               parentOffset + toIndex);
            this.modCount = parent.modCount;
            this.size -= toIndex - fromIndex;
        }

        public boolean addAll(Collection<? extends E> c) {
            return addAll(this.size, c);
        }

        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
            int cSize = c.size();
            if (cSize==0)
                return false;

            checkForComodification();
            parent.addAll(parentOffset + index, c);
            this.modCount = parent.modCount;
            this.size += cSize;
            return true;
        }

        public Iterator<E> iterator() {
            return listIterator();
        }

        public ListIterator<E> listIterator(final int index) {
            checkForComodification();
            rangeCheckForAdd(index);
            final int offset = this.offset;

            return new ListIterator<E>() {
                int cursor = index;
                int lastRet = -1;
                int expectedModCount = ArrayList.this.modCount;

                public boolean hasNext() {
                    return cursor != SubList.this.size;
                }

                @SuppressWarnings("unchecked")
                public E next() {
                    checkForComodification();
                    int i = cursor;
                    if (i >= SubList.this.size)
                        throw new NoSuchElementException();
                    Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i + 1;
                    return (E) elementData[offset + (lastRet = i)];
                }

                public boolean hasPrevious() {
                    return cursor != 0;
                }

                @SuppressWarnings("unchecked")
                public E previous() {
                    checkForComodification();
                    int i = cursor - 1;
                    if (i < 0)
                        throw new NoSuchElementException();
                    Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i;
                    return (E) elementData[offset + (lastRet = i)];
                }

                @SuppressWarnings("unchecked")
                public void forEachRemaining(Consumer<? super E> consumer) {
                    Objects.requireNonNull(consumer);
                    final int size = SubList.this.size;
                    int i = cursor;
                    if (i >= size) {
                        return;
                    }
                    final Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length) {
                        throw new ConcurrentModificationException();
                    }
                    while (i != size && modCount == expectedModCount) {
                        consumer.accept((E) elementData[offset + (i++)]);
                    }
                    // update once at end of iteration to reduce heap write traffic
                    lastRet = cursor = i;
                    checkForComodification();
                }

                public int nextIndex() {
                    return cursor;
                }

                public int previousIndex() {
                    return cursor - 1;
                }

                public void remove() {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try {
                        SubList.this.remove(lastRet);
                        cursor = lastRet;
                        lastRet = -1;
                        expectedModCount = ArrayList.this.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                public void set(E e) {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try {
                        ArrayList.this.set(offset + lastRet, e);
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                public void add(E e) {
                    checkForComodification();

                    try {
                        int i = cursor;
                        SubList.this.add(i, e);
                        cursor = i + 1;
                        lastRet = -1;
                        expectedModCount = ArrayList.this.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                final void checkForComodification() {
                    if (expectedModCount != ArrayList.this.modCount)
                        throw new ConcurrentModificationException();
                }
            };
        }

        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, offset, fromIndex, toIndex);
        }

        private void rangeCheck(int index) {
            if (index < 0 || index >= this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

        private void rangeCheckForAdd(int index) {
            if (index < 0 || index > this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

        private String outOfBoundsMsg(int index) {
            return "Index: "+index+", Size: "+this.size;
        }

        private void checkForComodification() {
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
        }

        public Spliterator<E> spliterator() {
            checkForComodification();
            return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                               offset + this.size, this.modCount);
        }
    }

    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }


    @Override
    public Spliterator<E> spliterator() {
        return new ArrayListSpliterator<>(this, 0, -1, 0);
    }

    /** Index-based split-by-two, lazily initialized Spliterator */
    static final class ArrayListSpliterator<E> implements Spliterator<E> {

        private final ArrayList<E> list;
        private int index; // current index, modified on advance/split
        private int fence; // -1 until used; then one past last index
        private int expectedModCount; // initialized when fence set

        /** Create new spliterator covering the given  range */
        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                             int expectedModCount) {
            this.list = list; // OK if null unless traversed
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

        private int getFence() { // initialize fence to size on first use
            int hi; // (a specialized variant appears in method forEach)
            ArrayList<E> lst;
            if ((hi = fence) < 0) {
                if ((lst = list) == null)
                    hi = fence = 0;
                else {
                    expectedModCount = lst.modCount;
                    hi = fence = lst.size;
                }
            }
            return hi;
        }

        public ArrayListSpliterator<E> trySplit() {
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null : // divide range in half unless too small
                new ArrayListSpliterator<E>(list, lo, index = mid,
                                            expectedModCount);
        }

        public boolean tryAdvance(Consumer<? super E> action) {
            if (action == null)
                throw new NullPointerException();
            int hi = getFence(), i = index;
            if (i < hi) {
                index = i + 1;
                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
                action.accept(e);
                if (list.modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            int i, hi, mc; // hoist accesses and checks from loop
            ArrayList<E> lst; Object[] a;
            if (action == null)
                throw new NullPointerException();
            if ((lst = list) != null && (a = lst.elementData) != null) {
                if ((hi = fence) < 0) {
                    mc = lst.modCount;
                    hi = lst.size;
                }
                else
                    mc = expectedModCount;
                if ((i = index) >= 0 && (index = hi) <= a.length) {
                    for (; i < hi; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) a[i];
                        action.accept(e);
                    }
                    if (lst.modCount == mc)
                        return;
                }
            }
            throw new ConcurrentModificationException();
        }

        public long estimateSize() {
            return (long) (getFence() - index);
        }

        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }
	
}

標記介面,Marker interface,它們是一類沒有定義任何介面方法的介面,表現為一個空介面 
沒有介面方法意味著實現該介面的類無需實現任何介面方法,僅僅作為一種標記,以供其他方法判斷 
作用就是當某個類實現這個介面後即擁有了這個介面的功能,Java 虛擬機器在執行時會識別到它 
標記介面是Java的語言特性 

在電腦科學中,隨機訪問(RandomAccess)是從大量的可定址元素的資料中訪問任何元素大致和訪問其他元素一樣簡潔有效,不管多少元素在這個集合中。與隨機訪問相反的是順序訪問(SequenceAccess)

 

RandomAccess 就是一個標記介面,用於標明實現該介面的List支援快速隨機訪問,主要目的是使演算法能夠在隨機和順序訪問的List中效能更加高效(在Collections二分查詢時)。 
Collections的binarySearch方法:

public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
    if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
        return Collections.indexedBinarySearch(list, key);
    else
        return Collections.iteratorBinarySearch(list, key);
}

在進行二分查詢時,首先判斷list是否實現了RandomAccess,然後選擇執行最優演算法。 
如果集合類是RandomAccess的實現,則儘量用for(int i = 0; i < size; i++) 即for迴圈來遍歷,而不是用Iterator 
迭代器來進行迭代。

JDK中說的很清楚,在對List特別是Huge size的List的遍歷演算法中,要儘量來判斷是屬於RandomAccess(如:ArrayList)還是SequenceAccess(如:LinkedList)

package java.util;

public interface RandomAccess {

}

RandomAccess是一個空介面,而空介面的作用一般是起到一個標識的作用。 
通俗點講,就是判斷一個list是否實現了RandomAcess介面,如果實現了,採用簡單的for迴圈進行訪問速度比較快。 
如果未實現RandomAcess介面,則採用iterator迴圈訪問速度比較快。 
判斷使用instanceof,即

if (list instanceof RandomAccess) 

 

Cloneable介面是一個標記介面,也就是沒有任何內容,定義如下:

package java.lang;

public interface Cloneable {
}

這裡分析一下這個介面的用法,clone方法是在Object種定義的,而且是protected型的,只有實現了這個介面,才可以在該類的例項上呼叫clone方法,否則會丟擲CloneNotSupportException。Object中預設的實現是一個淺拷貝,也就是表面拷貝,如果需要實現深層次拷貝的話,必須對類中可變域生成新的例項。
Object提供了一個物件拷貝的預設方法clone方法,但是該方法是有缺陷的,它提供了一種淺拷貝方式,也就是它並不會把物件所有屬性全部拷貝一份,而是有選擇性的拷貝,拷貝規則如下:

1、基本型別
如果變數是基本型別,則拷貝其值,比如:int、float、long等。

2、String字串
這個比較特殊,拷貝的是地址,是個引用,但是在修改的時候,它會從字串池(String Pool)中重新生成新的字串,原有的字串物件保持不變,此處可以認為String是個基本型別。

3、物件
如果變數時一個例項物件,則拷貝地址引用,也就是說此時新拷貝出的物件與原有物件共享該例項變數,不受訪問許可權的限制。這在Java中很瘋狂,因為它突破了訪問許可權的定義,一個private修飾的變數,竟然可以被兩個例項物件訪問。
Cloneable介面如下:如果呼叫Object的clone方法,沒有實現Cloneable介面,則會丟擲CloneNotSupportedException

淺克隆

import java.util.Date;

public class ShallowCopy implements Cloneable {
    private Date begin;
    public Date getBegin(){
        return this.begin;
    }
    public void setBegin(Date d){
        this.begin = d;
    }
    public Object clone(){
        Object obj = null;
        try{
            obj = super.clone();
        }catch(CloneNotSupportedException ex){
            ex.printStackTrace();
        }
        return obj;
    }
    public static void main(String[] args) {
        Date date = new Date(10000L);
        ShallowCopy copy = new ShallowCopy();
        copy.setBegin(date);
        ShallowCopy copy2 = (ShallowCopy) copy.clone();
        System.out.println(copy.getBegin() + "\n" 
                        + copy2.getBegin() + "\n" + 
                         (copy == copy2));
        date.setTime(100000000L);;
        System.out.println(copy.getBegin() + "\n" 
                + copy2.getBegin() + "\n" + 
                 (copy == copy2));
    }
//    Thu Jan 01 08:00:10 CST 1970
//    Thu Jan 01 08:00:10 CST 1970
//    false
//    Fri Jan 02 11:46:40 CST 1970
//    Fri Jan 02 11:46:40 CST 1970
//    false
}

深度克隆

public class DeepCopy implements Cloneable{
    private Date begin;
    public Date getBegin(){
        return this.begin;
    }
    public void setBegin(Date d){
        this.begin = d;
    }
    public Object clone(){
        DeepCopy obj = null;
        try{
            obj = (DeepCopy)super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        obj.setBegin((Date)this.getBegin().clone());
        return obj;
    }
    public static void main(String[] args) {
        Date date = new Date(10000L);
        DeepCopy copy = new DeepCopy();
        copy.setBegin(date);
        DeepCopy copy2 = (DeepCopy) copy.clone();
        System.out.println(copy.getBegin() + "\n" 
                        + copy2.getBegin() + "\n" + 
                         (copy == copy2));
        date.setTime(100000000L);
        System.out.println(copy.getBegin() + "\n" 
                + copy2.getBegin() + "\n" + 
                 (copy == copy2));
    }
//    Thu Jan 01 08:00:10 CST 1970
//    Thu Jan 01 08:00:10 CST 1970
//    false
//    Fri Jan 02 11:46:40 CST 1970
//    Thu Jan 01 08:00:10 CST 1970
//    false

 

AbstractList

此類提供的骨幹實現的List介面以最小化來實現該介面由一個“隨機訪問”資料儲存備份所需的工作(如陣列)。 對於順序存取的資料(如連結列表), AbstractSequentialList應優先使用此類。 
要實現一個不可修改的列表,程式設計師只需要擴充套件這個類並提供get(int)和size()方法的實現。 

要實現可修改的列表,程式設計師必須另外覆蓋set(int, E)方法(否則會丟擲一個UnsupportedOperationException )。 如果列表是可變大小,則程式設計師必須另外覆蓋add(int, E)和remove(int)方法。 

根據Collection介面規範中的建議,程式設計師通常應該提供一個void(無引數)和集合建構函式。 

不像其他的抽象集合實現,程式設計師不必提供迭代器實現; 迭代器和列表迭代器由此類實現的,對的“隨機訪問”方法上: get(int) , set(int, E) , add(int, E)和remove(int) 。 

該類中每個非抽象方法的文件詳細描述了其實現。 如果正在實施的集合承認更有效的實現,則可以覆蓋這些方法中的每一種。 

Modifier and Type Method and Description
boolean add(E e)

將指定的元素追加到此列表的末尾(可選操作)。

void add(int index, E element)

將指定的元素插入此列表中的指定位置(可選操作)。

boolean addAll(int index, Collection<? extends E> c)

將指定集合中的所有元素插入到此列表中的指定位置(可選操作)。

void clear()

從此列表中刪除所有元素(可選操作)。

boolean equals(Object o)

將指定的物件與此列表進行比較以獲得相等性。

abstract E get(int index)

返回此列表中指定位置的元素。

int hashCode()

返回此列表的雜湊碼值。

int indexOf(Object o)

返回此列表中指定元素的第一次出現的索引,如果此列表不包含元素,則返回-1。

Iterator<E> iterator()

以正確的順序返回該列表中的元素的迭代器。

int lastIndexOf(Object o)

返回此列表中指定元素的最後一次出現的索引,如果此列表不包含元素,則返回-1。

ListIterator<E> listIterator()

返回列表中的列表迭代器(按適當的順序)。

ListIterator<E> listIterator(int index)

從列表中的指定位置開始,返回列表中的元素(按正確順序)的列表迭代器。

E remove(int index)

刪除該列表中指定位置的元素(可選操作)。

protected void removeRange(int fromIndex, int toIndex)

從此列表中刪除所有索引在 fromIndex之間的 fromIndex ,包括 toIndex ,獨家。

E set(int index, E element)

用指定的元素(可選操作)替換此列表中指定位置的元素。

List<E> subList(int fromIndex, int toIndex)

返回此列表中指定的 fromIndex (含)和 toIndex之間的檢視。


package java.util;


public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    
    protected AbstractList() {
    }

    public boolean add(E e) {
        add(size(), e);
        return true;
    }

    abstract public E get(int index);

    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }

    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

    public E remove(int index) {
        throw new UnsupportedOperationException();
    }


    // Search Operations
    public int indexOf(Object o) {
        ListIterator<E> it = listIterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return it.previousIndex();
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return it.previousIndex();
        }
        return -1;
    }

    public int lastIndexOf(Object o) {
        ListIterator<E> it = listIterator(size());
        if (o==null) {
            while (it.hasPrevious())
                if (it.previous()==null)
                    return it.nextIndex();
        } else {
            while (it.hasPrevious())
                if (o.equals(it.previous()))
                    return it.nextIndex();
        }
        return -1;
    }


    // Bulk Operations

    public void clear() {
        removeRange(0, size());
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        boolean modified = false;
        for (E e : c) {
            add(index++, e);
            modified = true;
        }
        return modified;
    }


    // Iterators
    public Iterator<E> iterator() {
        return new Itr();
    }

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

    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

    private class Itr implements Iterator<E> {
        int cursor = 0;

        int lastRet = -1;

        int expectedModCount = modCount;

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

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

    private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public E previous() {
            checkForComodification();
            try {
                int i = cursor - 1;
                E previous = get(i);
                lastRet = cursor = i;
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor-1;
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.set(lastRet, e);
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                AbstractList.this.add(i, e);
                lastRet = -1;
                cursor = i + 1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return (this instanceof RandomAccess ?
                new RandomAccessSubList<>(this, fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));
    }

    // Comparison and hashing
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;

        ListIterator<E> e1 = listIterator();
        ListIterator<?> e2 = ((List<?>) o).listIterator();
        while (e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }

    public int hashCode() {
        int hashCode = 1;
        for (E e : this)
            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
        return hashCode;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        ListIterator<E> it = listIterator(fromIndex);
        for (int i=0, n=toIndex-fromIndex; i<n; i++) {
            it.next();
            it.remove();
        }
    }

    protected transient int modCount = 0;

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size())
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size();
    }
}

class SubList<E> extends AbstractList<E> {
    private final AbstractList<E> l;
    private final int offset;
    private int size;

    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
        l = list;
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }

    public E set(int index, E element) {
        rangeCheck(index);
        checkForComodification();
        return l.set(index+offset, element);
    }

    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return l.get(index+offset);
    }

    public int size() {
        checkForComodification();
        return size;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);
        checkForComodification();
        l.add(index+offset, element);
        this.modCount = l.modCount;
        size++;
    }

    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = l.remove(index+offset);
        this.modCount = l.modCount;
        size--;
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        l.removeRange(fromIndex+offset, toIndex+offset);
        this.modCount = l.modCount;
        size -= (toIndex-fromIndex);
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;

        checkForComodification();
        l.addAll(offset+index, c);
        this.modCount = l.modCount;
        size += cSize;
        return true;
    }

    public Iterator<E> iterator() {
        return listIterator();
    }

    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);

        return new ListIterator<E>() {
            private final ListIterator<E> i = l.listIterator(index+offset);

            public boolean hasNext() {
                return nextIndex() < size;
            }

            public E next() {
                if (hasNext())
                    return i.next();
                else
                    throw new NoSuchElementException();
            }

            public boolean hasPrevious() {
                return previousIndex() >= 0;
            }

            public E previous() {
                if (hasPrevious())
                    return i.previous();
                else
                    throw new NoSuchElementException();
            }

            public int nextIndex() {
                return i.nextIndex() - offset;
            }

            public int previousIndex() {
                return i.previousIndex() - offset;
            }

            public void remove() {
                i.remove();
                SubList.this.modCount = l.modCount;
                size--;
            }

            public void set(E e) {
                i.set(e);
            }

            public void add(E e) {
                i.add(e);
                SubList.this.modCount = l.modCount;
                size++;
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new SubList<>(this, fromIndex, toIndex);
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    private void checkForComodification() {
        if (this.modCount != l.modCount)
            throw new ConcurrentModificationException();
    }
}

class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
        super(list, fromIndex, toIndex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new RandomAccessSubList<>(this, fromIndex, toIndex);
    }
}


 

AbstractCollection

該類提供了Collection介面的骨架實現,以儘量減少實現此介面所需的工作量。 
為了實現一個不可修改的集合,程式設計師只需要擴充套件這個類並提供iterator和size方法的實現。 ( iterator方法返回的迭代器必須實現hasNext和next ) 

要實現可修改的集合,程式設計師必須另外覆蓋此類的add方法(否則將丟擲UnsupportedOperationException ),並且由iterator方法返回的迭代器必須另外實現其remove方法。 

程式設計師通常應該提供一個空隙(無引數)和Collection構造,按照在Collection介面規範的建議。 

該類中每個非抽象方法的文件詳細描述了其實現。 如果正在實施的集合承認更有效的實現,則可以覆蓋這些方法中的每一種。 

Modifier and Type Method and Description
boolean add(E e)

確保此集合包含指定的元素(可選操作)。

boolean addAll(Collection<? extends E> c)

將指定集合中的所有元素新增到此集合(可選操作)。

void clear()

從此集合中刪除所有元素(可選操作)。

boolean contains(Object o)

如果此集合包含指定的元素,則返回 true 。

boolean containsAll(Collection<?> c)

如果此集合包含指定 集合中的所有元素,則返回true。

boolean isEmpty()

如果此集合不包含元素,則返回 true 。

abstract Iterator<E> iterator()

返回包含在該集合中的元素的迭代器。

boolean remove(Object o)

從該集合中刪除指定元素的單個例項(如果存在)(可選操作)。

boolean removeAll(Collection<?> c)

刪除指定集合中包含的所有此集合的元素(可選操作)。

boolean retainAll(Collection<?> c)

僅保留此集合中包含在指定集合中的元素(可選操作)。

abstract int size()

返回此集合中的元素數。

Object[] toArray()

返回一個包含此集合中所有元素的陣列。

<T> T[] toArray(T[] a)

返回包含此集合中所有元素的陣列; 返回的陣列的執行時型別是指定陣列的執行時型別。

String toString()

返回此集合的字串表示形式。

package java.util;


public abstract class AbstractCollection<E> implements Collection<E> {

    protected AbstractCollection() {
    }

    // Query Operations
    public abstract Iterator<E> iterator();

    public abstract int size();

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

    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 (o.equals(it.next()))
                    return true;
        }
        return false;
    }

    public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) // fewer elements than expected
                return Arrays.copyOf(r, i);
            r[i] = it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size);
        Iterator<E> it = iterator();

        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) { // fewer elements than expected
                if (a == r) {
                    r[i] = null; // null-terminate
                } else if (a.length < i) {
                    return Arrays.copyOf(r, i);
                } else {
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        // more elements than expected
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    @SuppressWarnings("unchecked")
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
        int i = r.length;
        while (it.hasNext()) {
            int cap = r.length;
            if (i == cap) {
                int newCap = cap + (cap >> 1) + 1;
                // overflow-conscious code
                if (newCap - MAX_ARRAY_SIZE > 0)
                    newCap = hugeCapacity(cap + 1);
                r = Arrays.copyOf(r, newCap);
            }
            r[i++] = (T)it.next();
        }
        // trim if overallocated
        return (i == r.length) ? r : Arrays.copyOf(r, i);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError
                ("Required array size too large");
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

    // Modification Operations
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

    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 (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }


    // Bulk Operations
    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }


    //  String conversion
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

}

List

有序集合(也稱為序列 )。 該介面的使用者可以精確控制列表中每個元素的插入位置。 使用者可以通過整數索引(列表中的位置)訪問元素,並搜尋列表中的元素。 
與集合不同,列表通常允許重複的元素。 更正式地,列表通常允許元素e1和e2成對使得e1.equals(e2) ,並且如果它們允許空元素,它們通常允許多個空元素。 有人可能希望實現一個禁止重複的列表,當用戶嘗試插入時會丟擲執行時異常,但是我們預計這種使用是罕見的。 

該List介面放置額外的約定,超過在Collection指定介面上的iterator,add,remove,equals和hashCode方法合同。 其他繼承方法的宣告也包括在這裡以方便。 

List介面提供四種位置(索引)訪問列表元素的方法。 列表(如Java陣列)為零。 請注意,這些操作可能與某些實現的索引值(例如LinkedList類)成時執行。 因此,如果呼叫者不知道實現,則通過迭代列表中的元素通常優先於索引。 

所述List介面提供了一個特殊的迭代器,稱為ListIterator,其允許元件插入和更換,並且除了該Iterator介面提供正常操作的雙向訪問。 提供了一種方法來獲取從列表中的指定位置開始的列表迭代器。 

List介面提供了兩種方法來搜尋指定的物件。 從效能角度來說,謹慎使用這些方法。 在許多實現中,它們將執行昂貴的線性搜尋。 

List介面提供了兩種方法來有效地插入和