java之深入理解List.subList()方法
removeRange(int, int);這個方法AbstractList並沒有暴露出來,我們應該如何得到一個截短的list?
1 如何得到一個list某個範圍的子集sublist
首先想到sublist(int, int)方法
注意此方法引數左閉右開。
測試如下
1.1 修改sublist會影響原來的list
LinkedList<String> ll = new LinkedList<>();
ll.add("a");
ll.add("b");
ll.add("c");
List<String> l2 = ll.subList(1, 2);
l2.add("new");
System.out.println(ll);
System.out.println(l2);
[a, b, new, c]
[b, new]
可見sublist是快照,sulist插入會影響原list
1.2 修改原list,則sublist的所有操作會報錯
LinkedList<String> ll = new LinkedList<>();
ll.add("a");
ll.add("b");
ll.add("c");
List<String> l2 = ll.subList(1, 2);//[)
ll.add("d");
System.out.println(ll);
System.out.println(l2);
Exception in thread “main” java.util.ConcurrentModificationException
at java.util.SubList.checkForComodification(AbstractList.java:769)
可見如果更改了原來的list,sublist的任何操作都會報錯,包括get() size(),listIterator()等所有呼叫checkForComodification()的地方。
2 如何正確的截斷一個List?
subList()返回的是List!是Sublist,而不是原來的型別。
2.1在java.util.AbstractList.subList(int fromIndex, int toIndex)的定義,返回的是java.util.SubList.SubLis:
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
宣告:
class SubList<E> extends AbstractList<E>{}
2.2 LinkedList並沒有覆蓋這個方法.ArryList自己覆蓋了這個方法,返回的是java.util.ArrayList.SubList:
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
宣告:
private class SubList extends AbstractList<E> implements RandomAccess {}
看來ArryList處處體現出RandomAccess介面的特性——支援隨機訪問。
2.3 我們看一下java.util.AbstractList.clear()方法,這正是我們需要的,Sublist的clear就是這個方法
public void clear() {
removeRange(0, size());
}
2.3.1 ArrayList的覆蓋
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
2.3.2 LinkedList的覆蓋
public void clear() {
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
}
3 根據1和2
截短一個List的正確姿勢:
list.subList(from, to).clear();
總之:
subList是返回一個映象而不是新示例 用了 得保證原來的list不能更改。
之前的拋異常是因為更改了原來的list而要使用sublist的時候必然報異常。
clear的這個跟這個問題說的是如何獲得一個list的某一段順便釋放其他節點。
這個操作後原來的list會擷取出來 型別不變。
而subList實際上返回的是java.util.Sublist或者java.util.ArrayList.Sublist。
相關文章
- 深入理解 Java 方法Java
- Java hashCode() 方法深入理解Java
- Java 乾貨之深入理解Java泛型Java泛型
- 深入理解Java SPI之入門篇Java
- 深入理解Java之執行緒池Java執行緒
- 深入理解Java之裝箱與拆箱Java
- 深入理解Java PriorityQueueJava
- 深入理解Java反射Java反射
- Java:IO:深入理解Java
- 深入理解Java HelloWorldJava
- 深入理解Java虛擬機器之實戰OutOfMemoryErrorJava虛擬機Error
- 深入理解Java虛擬機器之垃圾回收篇Java虛擬機
- 深入理解 Java 註解Java
- 深入理解 Java 泛型Java泛型
- 深入理解 Java 列舉Java
- Java集合——深入理解HashMapJavaHashMap
- 深入理解 Java 陣列Java陣列
- 深入理解Java異常Java
- 深入理解Java反射(一)Java反射
- 深入理解Java泛型Java泛型
- 深入理解Javascript之PromiseJavaScriptPromise
- 深入理解Javascript之ModuleJavaScript
- 深入理解JVM之OOMJVMOOM
- 深入理解java虛擬機器之垃圾收集器Java虛擬機
- 深入理解Java虛擬機器之自己編譯JDKJava虛擬機編譯JDK
- 【Java】深入理解ReentrantLock可重入鎖之簡單使用JavaReentrantLock
- 深入理解 Java 序列化Java
- 深入理解Java I/O模型Java模型
- 深入理解Java中的鎖Java
- 深入理解 Java 中的 LambdaJava
- 深入理解Java中的AQSJavaAQS
- Java基礎——深入理解反射Java反射
- Java 集合深入理解(3):CollectionJava
- 深入理解Java的==和equalsJava
- 深入探討、理解Java的CLASSPATHJava
- 深入理解Java物件結構Java物件
- 深入理解 Golang 之 contextGolangContext
- 深入理解 Javascript 之 作用域JavaScript