1. 刪除類
1.1 E remove()、E removeFirst()
remove() 底層呼叫 removeFirst(),移除第一個元素,會報 NoSuchElementException 異常
public E remove ( ) {
return removeFirst ( ) ;
}
public E removeFirst ( ) {
final Node< E> f = first;
if ( f == null)
throw new NoSuchElementException ( ) ;
return unlinkFirst ( f) ;
}
1.2 E remove(int index)
public E remove ( int index) {
checkElementIndex ( index) ;
return unlink ( node ( index) ) ;
}
E unlink ( Node< E> x) {
final E element = x. item;
final Node< E> next = x. next;
final Node< E> prev = x. prev;
if ( prev == null) {
first = next;
} else {
prev. next = next;
x. prev = null;
}
if ( next == null) {
last = prev;
} else {
next. prev = prev;
x. next = null;
}
x. item = null;
size-- ;
modCount++ ;
return element;
}
1.3 boolean remove(Object o)
移除指定的元素,如果存在則返回true,不存在則返回 false
public boolean remove ( Object o) {
if ( o == null) {
for ( Node< E> x = first; x != null; x = x. next) {
if ( x. item == null) {
unlink ( x) ;
return true ;
}
}
} else {
for ( Node< E> x = first; x != null; x = x. next) {
if ( o. equals ( x. item) ) {
unlink ( x) ;
return true ;
}
}
}
return false ;
}
1.4 E removeLast()
與pollLast() 作用一直,不過 removeLast() 會報錯 NoSuchElementException
public E removeLast ( ) {
final Node< E> l = last;
if ( l == null)
throw new NoSuchElementException ( ) ;
return unlinkLast ( l) ;
}
1.5 boolean removeFirstOccurrence(Object o)
刪除第一個出現的元素,實際上底層呼叫的是 remove(Object o)
public boolean removeFirstOccurrence ( Object o) {
return remove ( o) ;
}
1.6 boolean removeLastOccurrence(Object o)
後面遍歷刪除出現的元素,底層呼叫 unlink(Node x)
public boolean removeLastOccurrence ( Object o) {
if ( o == null) {
for ( Node< E> x = last; x != null; x = x. prev) {
if ( x. item == null) {
unlink ( x) ;
return true ;
}
}
} else {
for ( Node< E> x = last; x != null; x = x. prev) {
if ( o. equals ( x. item) ) {
unlink ( x) ;
return true ;
}
}
}
return false ;
}
1.7 boolean removeAll(Collection<?> c)
刪除與 集合 c 相同的元素,並返回true,沒發生刪除,返回 false
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;
}
1.8 boolean retainAll(Collection<?> c)
刪除與 集合 c 不相同的元素,並返回true,若沒發生刪除,返回 false
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;
}
1.9 總結
remove() 底層呼叫 removeFirst(),會報 NoSuchElementException 異常 remove(int index) 與 remove(Object o) 都是先找到指定的 Node,然後呼叫 unlink(Node x) 學會 linkedList 的主要思想,prev,next指標 決定元素的順序,若查詢第 index 個,則只需 index 次 x = x.next(),若刪除,將 x節點 的prev,next指標指向的node節點記錄,斷開 x節點 的 prev,next指標,將 prev節點 的 next指標執向 next節點,將 next節點的prev指標指向 prev節點 程式碼示例
import java. util. ArrayList;
import java. util. LinkedList;
public class RemoveTest {
public static void main ( String[ ] args) {
LinkedList< Integer> linkedList = new LinkedList < > ( ) ;
for ( int i = 1 ; i <= 15 ; i++ ) {
linkedList. addLast ( i * 10 ) ;
}
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.remove(new Integer(10)): " + linkedList. remove ( new Integer ( 10 ) ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.remove(0) " + linkedList. remove ( 0 ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.remove(): " + linkedList. remove ( ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.removeFirst(): " + linkedList. removeFirst ( ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.removeFirstOccurrence(new Integer(100)): " + linkedList. removeFirstOccurrence ( new Integer ( 100 ) ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.removeLast(): " + linkedList. removeLast ( ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.removeLastOccurrence(new Integer(90)): " + linkedList. removeLastOccurrence ( new Integer ( 90 ) ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
ArrayList< Integer> arrayList01 = new ArrayList < Integer> ( ) { {
add ( 50 ) ;
add ( 60 ) ;
} } ;
ArrayList< Integer> arrayList02 = new ArrayList < Integer> ( ) { {
add ( 70 ) ;
add ( 80 ) ;
} } ;
System. out. println ( "linkedList.removeAll(arrayList01) : " + linkedList. removeAll ( arrayList01) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.retainAll(arrayList02) : " + linkedList. retainAll ( arrayList02) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "linkedList.removeIf((e) -> e % 20 == 0): " + linkedList. removeIf ( ( e) - > e % 20 == 0 ) ) ;
System. out. println ( "now linkedList: " + linkedList) ;
linkedList. replaceAll ( ( e) - > e * 10 ) ;
System. out. println ( "replaceAll((e) -> e * 10), now linkedList: " + linkedList) ;
}
}
2. LinkedList 的 迭代器 Iterator
2.1 ListItr 列表迭代器
private class ListItr implements ListIterator < E> {
private Node< E> lastReturned;
private Node< E> next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr ( int index) {
next = ( index == size) ? null : node ( index) ;
nextIndex = index;
}
public boolean hasNext ( ) {
return nextIndex < size;
}
public E next ( ) {
checkForComodification ( ) ;
if ( ! hasNext ( ) )
throw new NoSuchElementException ( ) ;
lastReturned = next;
next = next. next;
nextIndex++ ;
return lastReturned. item;
}
public boolean hasPrevious ( ) {
return nextIndex > 0 ;
}
public E previous ( ) {
checkForComodification ( ) ;
if ( ! hasPrevious ( ) )
throw new NoSuchElementException ( ) ;
lastReturned = next = ( next == null) ? last : next. prev;
nextIndex-- ;
return lastReturned. item;
}
public int nextIndex ( ) {
return nextIndex;
}
public int previousIndex ( ) {
return nextIndex - 1 ;
}
public void remove ( ) {
checkForComodification ( ) ;
if ( lastReturned == null)
throw new IllegalStateException ( ) ;
Node< E> lastNext = lastReturned. next;
unlink ( lastReturned) ;
if ( next == lastReturned)
next = lastNext;
else
nextIndex-- ;
lastReturned = null;
expectedModCount++ ;
}
public void set ( E e) {
if ( lastReturned == null)
throw new IllegalStateException ( ) ;
checkForComodification ( ) ;
lastReturned. item = e;
}
public void add ( E e) {
checkForComodification ( ) ;
lastReturned = null;
if ( next == null)
linkLast ( e) ;
else
linkBefore ( e, next) ;
nextIndex++ ;
expectedModCount++ ;
}
public void forEachRemaining ( Consumer< ? super E> action) {
Objects. requireNonNull ( action) ;
while ( modCount == expectedModCount && nextIndex < size) {
action. accept ( next. item) ;
lastReturned = next;
next = next. next;
nextIndex++ ;
}
checkForComodification ( ) ;
}
final void checkForComodification ( ) {
if ( modCount != expectedModCount)
throw new ConcurrentModificationException ( ) ;
}
}
import java. util. LinkedList;
import java. util. ListIterator;
public class ListIteratorTest {
public static void main ( String[ ] args) {
LinkedList< Integer> linkedList = new LinkedList < > ( ) ;
for ( int i = 1 ; i <= 8 ; i++ ) {
linkedList. add ( i * 10 ) ;
}
System. out. println ( "now linkedList: " + linkedList) ;
ListIterator< Integer> listIterator = linkedList. listIterator ( 0 ) ;
System. out. println ( "listIterator.next(): " + listIterator. next ( ) ) ;
System. out. println ( "listIterator.nextIndex(): " + listIterator. nextIndex ( ) ) ;
listIterator. add ( 100 ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "add(100)後,不會影響本來想取得下一個值 ,listIterator.nextIndex(): " + listIterator. nextIndex ( ) ) ;
System. out. println ( "listIterator.next(): " + listIterator. next ( ) ) ;
listIterator. add ( 120 ) ;
System. out. println ( "now linkedList: " + linkedList) ;
System. out. println ( "listIterator.hasPrevious(): " + listIterator. hasPrevious ( ) ) ;
System. out. println ( "listIterator.previous(): " + listIterator. previous ( ) ) ;
System. out. println ( "listIterator.next(): " + listIterator. next ( ) ) ;
}
}
2.2 DescendingIterator 倒序迭代器
new ListItr(size()) 得到 nextIndex 為 size 的 列表迭代器,所謂倒序迭代器,只是邏輯上的倒序,對於列表本身,由於雙向指向的存在,結構無需改變
private class DescendingIterator implements Iterator < E> {
privatefinal ListItr itr = new ListItr ( size ( ) ) ;
public boolean hasNext ( ) {
return itr. hasPrevious ( ) ;
}
public E next ( ) {
return itr. previous ( ) ;
}
public void remove ( ) {
itr. remove ( ) ;
}
}
import java. util. Iterator;
import java. util. LinkedList;
public class DescendingIteratorTest {
public static void main ( String[ ] args) {
LinkedList< Integer> linkedList = new LinkedList < > ( ) ;
for ( int i = 1 ; i <= 8 ; i++ ) {
linkedList. add ( i * 10 ) ;
}
System. out. println ( "now linkedList: " + linkedList) ;
Iterator< Integer> descendingIterator = linkedList. descendingIterator ( ) ;
System. out. println ( "descendingIterator.hasNext(): " + descendingIterator. hasNext ( ) ) ;
System. out. println ( "descendingIterator.next(): " + descendingIterator. next ( ) ) ;
}
}
2.3 LLSpliterator 分割迭代器
LinkedList 內建的分割器,可將 連結串列分割成多部分
static final class LLSpliterator < E> implements Spliterator < E> {
static final int BATCH_UNIT = 1 << 10 ;
static final int MAX_BATCH = 1 << 25 ;
final LinkedList< E> list;
Node< E> current;
int est;
int expectedModCount;
int batch;
LLSpliterator ( LinkedList< E> list, int est, int expectedModCount) {
this . list = list;
this . est = est;
this . expectedModCount = expectedModCount;
}
final int getEst ( ) {
int s;
final LinkedList< E> lst;
if ( ( s = est) < 0 ) {
if ( ( lst = list) == null)
s = est = 0 ;
else {
expectedModCount = lst. modCount;
current = lst. first;
s = est = lst. size;
}
}
return s;
}
public long estimateSize ( ) { return ( long ) getEst ( ) ; }
public Spliterator< E> trySplit ( ) {
Node< E> p;
int s = getEst ( ) ;
if ( s > 1 && ( p = current) != null) {
int n = batch + BATCH_UNIT;
if ( n > s)
n = s;
if ( n > MAX_BATCH)
n = MAX_BATCH;
Object[ ] a = new Object [ n] ;
int j = 0 ;
do { a[ j++ ] = p. item; } while ( ( p = p. next) != null && j < n) ;
current = p;
batch = j;
est = s - j;
return Spliterators. spliterator ( a, 0 , j, Spliterator. ORDERED) ;
}
return null;
}
public void forEachRemaining ( Consumer< ? super E> action) {
Node< E> p; int n;
if ( action == null) throw new NullPointerException ( ) ;
if ( ( n = getEst ( ) ) > 0 && ( p = current) != null) {
current = null;
est = 0 ;
do {
E e = p. item;
p = p. next;
action. accept ( e) ;
} while ( p != null && -- n > 0 ) ;
}
if ( list. modCount != expectedModCount)
throw new ConcurrentModificationException ( ) ;
}
public boolean tryAdvance ( Consumer< ? super E> action) {
Node< E> p;
if ( action == null) throw new NullPointerException ( ) ;
if ( getEst ( ) > 0 && ( p = current) != null) {
-- est;
E e = p. item;
current = p. next;
action. accept ( e) ;
if ( list. modCount != expectedModCount)
throw new ConcurrentModificationException ( ) ;
return true ;
}
return false ;
}
public int characteristics ( ) {
return Spliterator. ORDERED | Spliterator. SIZED | Spliterator. SUBSIZED;
}
}
程式碼示例,注意呼叫 trySplit() 後,使用的是 ArraySpliterator 迭代器
import java. util. LinkedList;
import java. util. Spliterator;
public class SpliteratorTest {
public static void main ( String[ ] args) {
LinkedList< Integer> linkedList = new LinkedList < > ( ) ;
linkedList. add ( 10 ) ;
linkedList. add ( 20 ) ;
linkedList. add ( 30 ) ;
linkedList. add ( 40 ) ;
linkedList. add ( 50 ) ;
linkedList. add ( 60 ) ;
Spliterator< Integer> spliterator = linkedList. spliterator ( ) ;
System. out. println ( "spliterator.getClass(): " + spliterator. getClass ( ) ) ;
System. out. println ( "spliterator.estimateSize(): " + spliterator. estimateSize ( ) ) ;
spliterator. tryAdvance ( ( e) - > System. out. println ( e) ) ;
System. out. println ( "spliterator.estimateSize(): " + spliterator. estimateSize ( ) ) ;
System. out. println ( "================================================" ) ;
Spliterator< Integer> integerSpliterator = spliterator. trySplit ( ) ;
integerSpliterator. tryAdvance ( ( e) - > System. out. println ( e) ) ;
System. out. println ( "spliterator.estimateSize(): " + spliterator. estimateSize ( ) ) ;
System. out. println ( "integerSpliterator.estimateSize(): " + integerSpliterator. estimateSize ( ) ) ;
System. out. println ( "integerSpliterator.getClass(): " + integerSpliterator. getClass ( ) ) ;
Spliterator< Integer> integerSpliterator01 = integerSpliterator. trySplit ( ) ;
System. out. println ( "integerSpliterator.estimateSize(): " + integerSpliterator. estimateSize ( ) ) ;
System. out. println ( "integerSpliterator01.estimateSize(): " + integerSpliterator01. estimateSize ( ) ) ;
System. out. println ( "integerSpliterator01.getClass(): " + integerSpliterator01. getClass ( ) ) ;
System. out. println ( "====== 分割完成後,各個遍歷器的未遍歷個數 =====" ) ;
System. out. println ( "spliterator.estimateSize(): " + spliterator. estimateSize ( ) ) ;
System. out. println ( "integerSpliterator.estimateSize(): " + integerSpliterator01. estimateSize ( ) ) ;
System. out. println ( "integerSpliterator01.estimateSize(): " + integerSpliterator01. estimateSize ( ) ) ;
}
}
3. 總結
若在遍歷時,需要對 LinkedList 的個數進行改動的話,需要使用 遍歷器 Iterator,切記不能使用for迴圈,否則報錯 ConcurrentModificationException LinkedList 內部有三個迭代器,列表迭代器 ListItr、 反序迭代器 DescendingIterator、分割迭代器LLSpliterator(在操作時,呼叫trySplit() 時使用ArraySpliterator)