为什么使用迭代器iterator遍历Linkedlist要比普通for快
2016-06-04 22:40
555 查看
</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;6263 final LinkedList<ET> list;6465 Link<ET> link, lastLink;6667 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 to72 // list.size - 173 // if link == voidLink then pos must == -174 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 }8889 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 }105106 public boolean hasNext() {107 return link.next != list.voidLink;108 }109110 public boolean hasPrevious() {111 return link != list.voidLink;112 }113114 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 }126127 public int nextIndex() {128 return pos + 1;129 }130131 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 }143144 public int previousIndex() {145 return pos;146 }147148 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 }170171 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;5051 Link<ET> previous, next;5253 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这里了
相关文章推荐
- 个人最终总结
- 计算机软件文档编写标准化
- 使用flying-saucer-pdf将html转pdf
- 实现二叉搜索树--查找、插入、删除
- 欢迎使用CSDN-markdown编辑器
- hdu5414 CRB and String
- 第二次冲刺周期站立会议(9)
- Android视频录制从不入门到入门系列教程(二)————显示视频图像
- Struts2-学习笔记系列(15)-ajax支持和JSON
- 个人工作总结09(第二次冲刺)
- Guava base -- Ascii
- 通过手势缩放、移动ImageView的图片
- 剑指offer22--链表的复制
- Struts2-学习笔记系列(14)-拦截器
- Android视频录制从不入门到入门系列教程(一)————简介
- Struts2-学习笔记系列(14)-拦截器
- 启动与关闭数据库实例
- 数据库编程细节问题 -- 2.mysql存储大文件
- LeetCode-69.Sqrt(x)
- Linux下的简易进度条的实现