以前講了兩種List,一種基於數組實現的ArrayList,一種基於鏈表實現的LinkedList,這兩種list是咱們工做中最經常使用到的List容器。固然數組和鏈表也是兩種常見的基本數據結構,其餘基本數據結構還有堆棧、隊列、樹等,對java容器的學習,也能夠看作是對數據結構的學習和使用。java
1
2
|
public
class
ArrayList<E>
extends
AbstractList<E>
implements
List<E>, RandomAccess, Cloneable, java.io.Serializable
|
LinkedList的定義:編程
1
2
3
|
public
class
LinkedList<E>
extends
AbstractSequentialList<E>
implements
List<E>, Deque<E>, Cloneable, java.io.Serializable
|
從定義上能夠看到ArrayList和LinkedList都實現了List接口,ok看下List接口的定義:設計模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public
interface
List<E>
extends
Collection<E> {
int
size();
boolean
isEmpty();
boolean
contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean
add(E e);
boolean
remove(Object o);
boolean
containsAll(Collection<?> c);
boolean
addAll(Collection<?
extends
E> c);
boolean
addAll(
int
index, Collection<?
extends
E> c);
boolean
removeAll(Collection<?> c);
boolean
retainAll(Collection<?> c);
void
clear();
boolean
equals(Object o);
int
hashCode();
E get(
int
index);
E set(
int
index, E element);
void
add(
int
index, E element);
E remove(
int
index);
int
indexOf(Object o);
int
lastIndexOf(Object o);
ListIterator<E> listIterator();
ListIterator<E> listIterator(
int
index);
List<E> subList(
int
fromIndex,
int
toIndex);
}
|
能夠看到List中對容器的各類操做add、remove、set、get、size等進行了統必定義,同時List實現了Collection接口,繼續看下Collection接口的定義(先不關心Iterator):數組
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
interface
Collection<E>
extends
Iterable<E> {
int
size();
boolean
isEmpty();
boolean
contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean
add(E e);
boolean
remove(Object o);
boolean
containsAll(Collection<?> c);
boolean
addAll(Collection<?
extends
E> c);
boolean
removeAll(Collection<?> c);
boolean
retainAll(Collection<?> c);
void
clear();
boolean
equals(Object o);
int
hashCode();
}<span style=
"font-weight: normal;"
> </span>
|
有了這兩個接口,對於ArrayList和LinkeList的操做是否是就能夠這麼寫了呢?數據結構
1
2
3
4
|
Collection<String> collection =
new
ArrayList<String>();
collection.add(
"hello"
);
collection.add(
"java"
);
collection.remove(
"hello"
);
|
對於ArrayList的實現不滿意,ok換成LinkedList實現,多線程
1
2
3
4
|
Collection<String> collection =
new
LinkedList<String>();
collection.add(
"hello"
);
collection.add(
"java"
);
collection.remove(
"hello"
);
|
對於用戶來講,add、remove等操做是沒有任何影響的,好了,到這裏瞭解了統一接口,面向接口編程的好處,接下來在思考另一個問題,怎麼給容器提供一種遍歷方式。dom
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** Implementing this interface allows an object to be the target of
* the "foreach" statement.
* @since 1.5
*/
public
interface
Iterable<T> {
/**
* Returns an iterator over a set of elements of type T.
*
* @return an Iterator.
*/
Iterator<T> iterator();
}
|
英文註釋說,實現iterable接口的類可使用「foreach」操做,而後並要求實現Iterator<T> iterator()方法,該方法返回一個Iterator接口對象,來看下Iterator接口,ide
1
2
3
4
5
6
7
8
|
public
interface
Iterator<E> {
// 是否還有元素
boolean
hasNext();
// 下一個元素
E next();
// 將迭代器返回的元素刪除
void
remove();
}
|
Iterator接口一共有三個方法,經過這三個方法就能夠實現通用遍歷了,ok,咱們來試一下。學習
1
2
3
4
5
6
7
8
|
Collection<String> collection =
new
ArrayList<String>();
collection.add(
"hello"
);
collection.add(
"java"
);
Iterator<String> iterator = collection.iterator();
while
(iterator.hasNext()) {
System. out.println(iterator.next());
}
|
1
2
3
4
|
public
interface
MyIterator {
Object next();
boolean
hasNext();
}
|
容器統一接口:this
1
2
3
4
5
|
public
interface
MyCollection {
void
add(Object o);
int
size();
MyIterator iterator();
}
|
容器實現類和Iterator實現類(Iterator實現類爲容器內部類):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
public
class
MyArrayList
implements
MyCollection {
private
Object[] data ;
private
int
size;
public
MyArrayList() {
data =
new
Object[
10
];
}
public
void
add(Object o) {
if
(size == data. length) {
Object[] newData =
new
Object[data .length *
2
];
System. arraycopy(data,
0
, newData,
0
, data.length );
data = newData;
}
data[size ] = o;
size++;
}
public
int
size() {
return
size ;
}
@Override
public
MyIterator iterator() {
return
new
Itr();
}
private
class
Itr
implements
MyIterator {
private
int
index =
0
;
@Override
public
boolean
hasNext() {
if
(index >= size) {
return
false
;
}
else
{
return
true
;
}
}
@Override
public
Object next() {
Object o = data[index ];
index++;
return
o;
}
}
}
|
應用一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
class
Test {
public
static
void
main(String[] args) {
MyCollection c =
new
MyArrayList();
c.add(
"t"
);
c.add(
"s"
);
c.add(
"t"
);
c.add(
"d"
);
System. out.println(c.size());
MyIterator itr = c.iterator();
while
(itr.hasNext()) {
System. out.println(itr.next());
}
}
}
|
1
2
3
4
5
|
4
t
s
t
d
|
沒問題,很容易就實現了對不對,固然這裏只是簡單模擬,沒有過多的追求效率和優雅的設計。
1
2
3
|
public
Iterator<E> iterator() {
return
new
Itr();
}<span style=
"font-weight: normal;"
> </span>
|
和本身實現的同樣,採用內部類實現 Iterator接口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
private
class
Itr
implements
Iterator<E> {
// 將要next返回元素的索引
int
cursor =
0
;
// 當前返回的元素的索引,初始值-1
int
lastRet = -
1
;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int
expectedModCount = modCount;
public
boolean
hasNext() {
// 因爲cursor是將要返回元素的索引,也就是下一個元素的索引,和size比較是否相等,也就是判斷是否已經next到最後一個元素
return
cursor != size();
}
public
E next() {
checkForComodification();
try
{
// 根據下一個元素索引取出對應元素
E next = get( cursor);
// 更新lastRet爲當前元素的索引,cursor加1
lastRet = cursor ++;
// 返回元素
return
next;
}
catch
(IndexOutOfBoundsException e) {
checkForComodification();
throw
new
NoSuchElementException();
}
}
public
void
remove() {
// remove前必須先next一下,先取得當前元素
if
(lastRet == -
1
)
throw
new
IllegalStateException();
checkForComodification();
try
{
AbstractList.
this
.remove(lastRet );
// 確保lastRet比cursor小、理論上永遠lastRet比cursor小1
if
(lastRet < cursor)
// 因爲刪除了一個元素cursor回退1
cursor--;
// 重置爲-1
lastRet = -
1
;
expectedModCount = modCount ;
}
catch
(IndexOutOfBoundsException e) {
throw
new
ConcurrentModificationException();
}
}
final
void
checkForComodification() {
if
(modCount != expectedModCount)
throw
new
ConcurrentModificationException();
}
}
|
1
2
3
|
public
Iterator<E> iterator() {
return
listIterator();
}
|
AbstractList的實現:
1
2
3
4
5
6
7
8
9
|
public
ListIterator<E> listIterator() {
return
listIterator(
0
);
}
public
ListIterator<E> listIterator(
final
int
index) {
if
(index<
0
|| index>size())
throw
new
IndexOutOfBoundsException(
"Index: "
+index);
return
new
ListItr(index);
}
|
看一下ListItr實現:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
private
class
ListItr
implements
ListIterator<E> {
// 最後一次返回的節點,默認位header節點
private
Entry<E> lastReturned = header;
// 將要返回的節點
private
Entry<E> next ;
// 將要返回的節點index索引
private
int
nextIndex;
private
int
expectedModCount = modCount;
ListItr(
int
index) {
// 索引越界檢查
if
(index <
0
|| index > size)
throw
new
IndexOutOfBoundsException(
"Index: "
+index+
", Size: "
+size );
// 簡單二分,判斷遍歷的方向
if
(index < (size >>
1
)) {
// 取得index位置對應的節點
next = header .next;
for
(nextIndex =
0
; nextIndex<index; nextIndex++)
next = next .next;
}
else
{
next = header ;
for
(nextIndex =size; nextIndex>index; nextIndex --)
next = next .previous;
}
}
public
boolean
hasNext() {
// 根據下一個節點index是否等於size,判斷是否有下一個節點
return
nextIndex != size;
}
public
E next() {
checkForComodification();
// 遍歷完成
if
(nextIndex == size)
throw
new
NoSuchElementException();
// 賦值最近一次返回的節點
lastReturned = next ;
// 賦值下一次要返回的節點(next後移)
next = next .next;
// 將要返回的節點index索引+1
nextIndex++;
return
lastReturned .element;
}
public
boolean
hasPrevious() {
return
nextIndex !=
0
;
}
// 返回上一個節點(雙向循環鏈表嘛、能夠兩個方向遍歷)
public
E previous() {
if
(nextIndex ==
0
)
throw
new
NoSuchElementException();
lastReturned = next = next. previous;
nextIndex--;
checkForComodification();
return
lastReturned .element;
}
public
int
nextIndex() {
return
nextIndex ;
}
public
int
previousIndex() {
return
nextIndex -
1
;
}
public
void
remove() {
checkForComodification();
// 取出當前返回節點的下一個節點
Entry<E> lastNext = lastReturned.next ;
try
{
LinkedList.
this
.remove(lastReturned );
}
catch
(NoSuchElementException e) {
throw
new
IllegalStateException();
}
// 確認下次要返回的節點不是當前節點,若是是則修正
if
(next ==lastReturned)
next = lastNext;
else
// 因爲刪除了一個節點,下次要返回的節點索引-1
nextIndex--;
// 重置lastReturned爲header節點
lastReturned = header ;
expectedModCount++;
}
public
void
set(E e) {
if
(lastReturned == header)
throw
new
IllegalStateException();
checkForComodification();
lastReturned.element = e;
}
public
void
add(E e) {
checkForComodification();
lastReturned = header ;
addBefore(e, next);
nextIndex++;
expectedModCount++;
}
final
void
checkForComodification() {
if
(modCount != expectedModCount)
throw
new
ConcurrentModificationException();
}
}<span style=
"font-weight: normal;"
> </span>
|