概念

java.util.Iterator接口主要用于描述迭代器对象,可以遍历Collection集合中的所有元素。

Iterator接口和Collection接口有什么关系??

  • java.util.Collection接口继承Iterator接口,因此所有实现Collection接口的实现类都可以使用该迭代器对象。

方法

方法声明 功能介绍
boolean hasNext() 判断集合中是否有可以迭代/访问的元素
E next() 用于取出一个元素并指向下一个元素
void remove() 用于删除访问到的最后一个元素

迭代打印集合

  1. public class CollectionPrint {
  2. public static void main(String[] args) {
  3. Collection c1 = new ArrayList();
  4. c1.add("hello");
  5. c1.add(66);
  6. //直接调用toString方法,对应的c1就是一个字符串打印出来 String类型的整体
  7. System.out.println("c1:"+c1);//[hello, 66]
  8. //第二种:用迭代器判断打印
  9. //2.遍历方式二:使用迭代器来遍历集合中的所有元素 更加灵活
  10. // 获取当前集合中的迭代器对象
  11. Iterator iterator = c1.iterator();
  12. // 判断是否有元素可以访问
  13. System.out.println(iterator.hasNext());//true
  14. // 取出下一个
  15. System.out.println(iterator.next());//hello
  16. // 判断是否有元素可以访问
  17. System.out.println(iterator.hasNext());//true
  18. // 取出下一个
  19. System.out.println(iterator.next());//66
  20. // 判断是否有元素可以访问
  21. System.out.println(iterator.hasNext());//false
  22. // 取出下一个
  23. //编译OK,运行发生NoSuchElementException 没有元素异常
  24. System.out.println(iterator.next());//NoSuchElementException
  25. }
  26. }
  • while循环替换:
  1. while (iterator.hasNext()){
  2. System.out.println(iterator.next());
  3. }

案例

  • 如何使用迭代器实现toString方法的打印效果?

上个循环已经使得迭代器走到了最后,因此需要重置迭代器

  1. System.out.println(c1);
  2. // 由于上个循环已经使得迭代器走到了最后,因此需要重置迭代器
  3. iterator = c1.iterator();
  4. StringBuilder s = new StringBuilder();
  5. s.append("[");
  6. while (iterator.hasNext()){
  7. Object next = iterator.next();
  8. if(!iterator.hasNext()){
  9. s.append(next).append("]");
  10. }else {
  11. // 否则拼接元素加逗号加空格
  12. s.append(next).append(",").append(" ");
  13. }
  14. }
  15. System.out.println(s);

里面的if对应的指针再次往下,去看是否有下一个元素,如果没有则就是最后一个元素

迭代删除元素

  • 迭代删除元素为66
  1. // 由于上个循环已经使得迭代器走到了最后,因此需要重置迭代器
  2. iterator = c1.iterator();
  3. //[hello, 66, Person{name='zhangfei', age=30}]
  4. while (iterator.hasNext()){
  5. Object next = iterator.next();
  6. System.out.println();
  7. if(next.equals(66)){
  8. //使用迭代器remove方法删除元素
  9. iterator.remove();
  10. }
  11. }
  12. System.out.println("迭代器删除元素后:"+c1);//[hello, Person{name='zhangfei', age=30}]
  • 如果在remove 时候使用集合的remove方法会发生什么?
  1. // 由于上个循环已经使得迭代器走到了最后,因此需要重置迭代器
  2. iterator = c1.iterator();
  3. Person zhangfei = new Person("zhangfei", 30);
  4. Integer d = 66;
  5. while (iterator.hasNext()){
  6. Object next = iterator.next();
  7. System.out.println(d.equals(next));
  8. if(d.equals(next)){
  9. c1.remove(next);
  10. }
  11. }
  12. System.out.println("迭代器删除元素后:"+c1);//[hello, Person{name='zhangfei', age=30}]
  13. }

集合-迭代器 - 图1

迭代一个集合的时候不允许去修改这个集合,如果修改,对应迭代结果是不确定的。

比如说,在班级里面我来数一下咱们班有多少个人,这个时候我正在数「其实就是迭代的过程」,但是这个时候班里面的人进进出出大量的人进进出出,会不会影响你数数。所以这个情况下迭代的结果就是不确定的,
如果检测到这个行为就抛出异常。

就像我睡不着了就开始数羊,一只羊、两只羊,然后这个时候有人给你来个电话,你是不是挂了电话就忘了自己数到了哪里了。
所以迭代器的hasNext就相当于在数一只羊一只羊,然后我再数的时候前面的羊没了「c1.remove相当于把我的羊弄没了」,它是不是就把我们迭代器破坏了

可以看到下面ArrayList里面的hasNext源码,在c1.remove完成了以后,对应的cursor=2,size=2,这个时候hasNext返回的是false,不会进入下一个循环,直接去打印了集合c1

  1. public boolean hasNext() {
  2. return cursor != size;
  3. }

所以在迭代器里面,自己迭代自己删除。不能让外面的对象过来操作我们的迭代内容。只要不是在迭代的过程中,用集合的remove方法是没有问题的。

总结:

  • 在迭代过程中不能对集合/数组对象进行操作,否则会报并发修改异常。
  • 更加灵活,但是没有toString洒脱,调用的方法比较多