</pre><p></p><pre name="code" class="java">
大家可以搜索一下普通情況遍歷linkedlist應該是O(n)但是使用iterator就是常數,這讓我很好奇。於是我去查了源碼。。
一路順着找找到了Collection,確實有一個iterator但是是個interface還沒有實現。
網上找list,有一個listiterator還是這樣。
只能去linked找了,找到了如下源碼
private static final class LinkIterator<ET> implements ListIterator<ET> {
61 int pos, expectedModCount;
62
63 final LinkedList<ET> list;
64
65 Link<ET> link, lastLink;
66
67 LinkIterator(LinkedList<ET> object, int location) {
68 list = object;
69 expectedModCount = list.modCount;
70 if (location >= 0 && location <= list.size) {
71 // pos ends up as -1 if list is empty, it ranges from -1 to
72 // list.size - 1
73 // if link == voidLink then pos must == -1
74 link = list.voidLink;
75 if (location < list.size / 2) {
76 for (pos = -1; pos + 1 < location; pos++) {
77 link = link.next;
78 }
79 } else {
80 for (pos = list.size; pos >= location; pos--) {
81 link = link.previous;
82 }
83 }
84 } else {
85 throw new IndexOutOfBoundsException();
86 }
87 }
88
89 public void add(ET object) {
90 if (expectedModCount == list.modCount) {
91 Link<ET> next = link.next;
92 Link<ET> newLink = new Link<ET>(object, link, next);
93 link.next = newLink;
94 next.previous = newLink;
95 link = newLink;
96 lastLink = null;
97 pos++;
98 expectedModCount++;
99 list.size++;
100 list.modCount++;
101 } else {
102 throw new ConcurrentModificationException();
103 }
104 }
105
106 public boolean hasNext() {
107 return link.next != list.voidLink;
108 }
109
110 public boolean hasPrevious() {
111 return link != list.voidLink;
112 }
113
114 public ET next() {
115 if (expectedModCount == list.modCount) {
116 LinkedList.Link<ET> next = link.next;
117 if (next != list.voidLink) {
118 lastLink = link = next;
119 pos++;
120 return link.data;
121 }
122 throw new NoSuchElementException();
123 }
124 throw new ConcurrentModificationException();
125 }
126
127 public int nextIndex() {
128 return pos + 1;
129 }
130
131 public ET previous() {
132 if (expectedModCount == list.modCount) {
133 if (link != list.voidLink) {
134 lastLink = link;
135 link = link.previous;
136 pos--;
137 return lastLink.data;
138 }
139 throw new NoSuchElementException();
140 }
141 throw new ConcurrentModificationException();
142 }
143
144 public int previousIndex() {
145 return pos;
146 }
147
148 public void remove() {
149 if (expectedModCount == list.modCount) {
150 if (lastLink != null) {
151 Link<ET> next = lastLink.next;
152 Link<ET> previous = lastLink.previous;
153 next.previous = previous;
154 previous.next = next;
155 if (lastLink == link) {
156 pos--;
157 }
158 link = previous;
159 lastLink = null;
160 expectedModCount++;
161 list.size--;
162 list.modCount++;
163 } else {
164 throw new IllegalStateException();
165 }
166 } else {
167 throw new ConcurrentModificationException();
168 }
169 }
170
171 public void set(ET object) {
172 if (expectedModCount == list.modCount) {
173 if (lastLink != null) {
174 lastLink.data = object;
175 } else {
176 throw new IllegalStateException();
177 }
178 } else {
179 throw new ConcurrentModificationException();
180 }
181 }
182 }
183
我們仔細察看next方法
public ET next() {
115 if (expectedModCount == list.modCount) {
116 LinkedList.Link<ET> next = link.next;
117 if (next != list.voidLink) {
118 lastLink = link = next;
119 pos++;
120 return link.data;
121 }
122 throw new NoSuchElementException();
123 }
124 throw new ConcurrentModificationException();
125 }
126
這裏裏面有一個類是叫link,代碼如下
private static final class Link<ET> {
49 ET data;
50
51 Link<ET> previous, next;
52
53 Link(ET o, Link<ET> p, Link<ET> n) {
54 data = o;
55 previous = p;
56 next = n;
57 }
58 }
可見list就是一個雙向鏈表的link,沒有什麼特殊之處。到這裏我徹底懵逼了,爲什麼呢爲什麼呢,爲什麼你遍歷就是常數呢?
我們仔細對比一下for循環
for(int i =0;i<list.size();i++){
list.get(i);
}
但是iterator和他對比起來少了一個list.get(i);其實就遍歷而言它們兩個差距並不大。但是其中調用了一次get(i).這個時間複雜度應該是O(n)所以嵌套一個for循環是O(n^2),但是在iterator中因爲next的存在get當前項不需要時間所以循環下來應該是O(n),原來差距就在get和iterator這裏了