subList傳回僅僅隻是一個視圖。直接上源碼
subListRangeCheck方式是判斷fromIndex、toIndex是否合法,如果合法就直接傳回一個subList對象,注意在産生該new該對象的時候傳遞了一個參數 this ,該參數非常重要,因為他代表着原始list。
該SubLsit是ArrayList的内部類,它與ArrayList一樣,都是繼承AbstractList和實作RandomAccess接口。同時也提供了get、set、add、remove等list常用的方法。但是它的構造函數有點特殊,在該構造函數中有兩個地方需要注意:
1、this.parent = parent;而parent就是在前面傳遞過來的list,也就是說this.parent就是原始list的引用。
2、this.offset = offset + fromIndex;this.parentOffset = fromIndex;。同時在構造函數中它甚至将modCount(fail-fast機制)傳遞過來了。
我們再看get方法,在get方法中return ArrayList.this.elementData(offset + index);這段代碼可以清晰表明get所傳回就是原清單offset + index位置的元素。同樣的道理還有add方法裡面的:
remove方法裡面的
誠然,到了這裡我們可以判斷subList傳回的SubList同樣也是AbstractList的子類,同時它的方法如get、set、add、remove等都是在原清單上面做操作,它并沒有像subString一樣生成一個新的對象。是以subList傳回的隻是原清單的一個視圖,它所有的操作最終都會作用在原清單上。
從上面我們知道subList生成的子清單隻是原清單的一個視圖而已,如果我們操作子清單它産生的作用都會在原清單上面表現,但是如果我們操作原清單會産生什麼情況呢?
該執行個體如果不産生意外,那麼他們兩個list的大小都應該都是3,但是偏偏事與願違,事實上我們得到的結果是這樣的:
list1正常輸出,但是list3就抛出ConcurrentModificationException異常。我們再看size方法:
size方法首先會通過checkForComodification驗證,然後再傳回this.size。
該方法表明當原清單的modCount與this.modCount不相等時就會抛出ConcurrentModificationException。同時我們知道modCount 在new的過程中 "繼承"了原清單modCount,隻有在修改該清單(子清單)時才會修改該值(先表現在原清單後作用于子清單)。而在該執行個體中我們是操作原清單,原清單的modCount當然不會反應在子清單的modCount上啦,是以才會抛出該異常。
對于子清單視圖,它是動态生成的,生成之後就不要操作原清單了,否則必然都導緻視圖的不穩定而抛出異常。最好的辦法就是将原清單設定為隻讀狀态,要操作就操作子清單:
在開發過程中我們一定會遇到這樣一個問題:擷取一堆資料後,需要删除某段資料。例如,有一個清單存在1000條記錄,我們需要删除100-200位置處的資料,我們可以這樣處理:
子清單的操作都會反映在原清單上。是以下面一行代碼全部搞定:
1.在使用asList時不要将基本資料類型當做參數。
2.asList傳回的清單隻不過是一個披着list的外衣(Arrays裡面的内部類ArrayList),它并沒有list的基本特性(變長)。該list是一個長度不可變的清單,傳入參數的數組有多長,其傳回的清單就隻能是多長。
使用工具類 Arrays.asList()把數組轉換成集合時,不能使用其修改集合相關的方 法,它的 add/remove/clear 方法會抛出 UnsupportedOperationException 異常。 說明:asList 的傳回對象是一個 Arrays 内部類,并沒有實作集合的修改方法。Arrays.asList 展現的是擴充卡模式,隻是轉換接口,背景的資料仍是數組。
第一種情況:list.add("c"); 運作時異常。
第二種情況:str[0]= "jinyong"; 那麼 list.get(0)也會随之修改