本来的遍历是这样的,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));
复制代码