之前讲了两种List,一种基于数组实现的ArrayList,一种基于链表实现的LinkedList,这两种list是我们工作中最常用到的List容器。当然数组和链表也是两种常见的基本数据结构,其他基本数据结构还有堆栈、队列、树等,对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等操作是没有任何影响的,好了,到这里了解了统一接口,面向接口编程的好处,接下来在思考另外一个问题,怎么给容器提供一种遍历方式。
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接口,
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(); } |
容器统一接口:
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> |