本來的遍歷是這樣的,java
List<Integer> list = new ArrayList<>();
//add
for(int i = 0 ;i < list;i++ ){
System.out.println(list.get(i));
}
複製代碼
而用了迭代器以後能夠是這樣的bash
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
複製代碼
或者這樣,數據結構
for (Integer i:list){
System.out.println(i);
}
複製代碼
java8 以後能夠用ide
list.forEach(item -> System.out.println(item));
//或者更加精簡
list.forEach(System.out::println);
複製代碼
舉個例子,好比要遍歷 LinkedList性能
若是不用迭代器,有些新手會寫成這樣測試
for(int i = 0 ; i < linkedList.size(); i++){
System.out.println(list.get(i));
}
複製代碼
知道,LinkedList 的數據結構的朋友,應該會知道這樣遍歷的時候複雜度會是 O(n^2) 而 LinkedList 的遍歷本應該是 O(n)。 這只是個簡單的例子,以小見大吧。面對未知的數據結構,或者在不熟悉項目且時候很緊,逼着要用之前的人寫的數據結構的時候,若是還要用最原始的方式進行遍歷,就會莫名其妙地給程序「留有優化的空間」。優化
也就是說,若是用了遍歷器模式,就在原來的數據結構上創建一個新的抽象,更加方便地進行遍歷。ui
從上面一個例子能夠看到this
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
複製代碼
好比有一個類是 Teacher ,他管理了不少學生。想經過這種方式遍歷要怎樣作呢?這樣就能夠了。spa
public class Teacher {
Student students[];
public Teacher(Student[] students) {
this.students = students;
}
public Iterator<Student> iterator() {
return new Iterator<Student>() {
int i = 0;
@Override
public boolean hasNext() {
return students != null && i != students.length;
}
@Override
public Student next() {
return students[i++];
}
};
}
}
複製代碼
若是是要作到相似容器那種 for-each 的效果?好比是這樣。
for (Student s : teacher) {
System.out.println(s);
}
teacher.forEach(System.out::println);
複製代碼
那就要額外實現一下 Iterable 接口了。
public class Teacher implements Iterable<Student> {
//...
@Override
public Iterator<Student> iterator() {
//...同上
}
@Override
public void forEach(Consumer<? super Student> action) {
for(Student s: students){
action.accept(s);
}
}
/** * 這個是用於 java8 的並行 foreach 的,運用的模式相似於迭代是,比較複雜先不寫了。 **/
@Override
public Spliterator<Student> spliterator() {
//TODO
return null;
}
}
複製代碼
用 100 萬條 簡單測試一下
int size = 1000000;
List<Integer> nums = new ArrayList<>();
for (int i = 0; i < size; i++) {
nums.add(i);
}
//傳統方式 用時 6ms
long start = System.currentTimeMillis();
for(int i = 0 ; i <size ;i++){
nums.get(i);
}
long end = System.currentTimeMillis();
System.out.println("傳統方式:" + (end - start));
//使用迭代器 用時:16ms
start = System.currentTimeMillis();
Iterator<Integer> iterator = nums.iterator();
while (iterator.hasNext()) {
iterator.next();
}
end =System.currentTimeMillis();
System.out.println("迭代器:" + (end - start));
//使用 foreach 語法糖 用時:17ms
start = System.currentTimeMillis();
for (Integer num : nums) {
}
end = System.currentTimeMillis();
System.out.println("foreach:" + (end - start));
//使用 lambda 接口 語法糖 用時:39ms
start = System.currentTimeMillis();
nums.forEach(num -> {});
end = System.currentTimeMillis();
System.out.println("lambda:" + (end - start));
//使用 stream 接口語法糖 用時: 14ms
start = System.currentTimeMillis();
nums.stream().forEach(s->{});
end = System.currentTimeMillis();
System.out.println("stream 接口語法糖:" + (end - start));
複製代碼