迭代器和加强for循环

Iterator迭代器的使用:

迭代:Iterator,即collection集合元素的通用获取方式java

java.util.Iterator接口。迭代器(对集合进行遍历)数组

有两个经常使用的方法安全

Boolean hasNext()若是仍有元素能够迭代,则返回true
判断集合中还有没有下一个元素,有就返回true,没有就返回false
E next()返回迭代的下一个元素
取出集合中的下一个元素jvm

Iterator迭代器,是一个接口,咱们没法直接使用,须要Iterator接口的实现类对象,获取实现类的方式比较特殊
Collection接口中有一个方法,叫Iterator(),这个方法返回的就是迭代器的实现类对象
Iterator iterator()返回在此collection的元素上进行迭代的迭代器ide

迭代器的使用步骤(重点)
一、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
二、使用Iterator接口中的方法hasNext判断还有没有下一个元素
三、使用Iterator接口中的方法next取出集合中的下一个元素优化

package Iterator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Demo01Collection {

    public static void main(String[] args) {
        //建立一个集合对象
        Collection<String> coll=new ArrayList<>();
        coll.add("星星");
        coll.add("仰望星空");
        coll.add("最美的太阳");
        coll.add("这就是爱");
        //一、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
        //Iterator<E>的接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型

        //多态     接口          实现类对象
        Iterator<String>  it=coll.iterator();

        //发现使用迭代器取出集合中元素的代码是一个重复的过程
        //因此咱们可使用循环优化
        //不知道集合中有多少元素,使用while集合
        //循环结束的条件,hasNext方法返回false
        while (it.hasNext()){
            String e=it.next();
            System.out.println(e);
        }

//        //二、使用Iterator接口中的方法hasNext判断还有没有下一个元素
//        boolean b=it.hasNext();
//        System.out.println(b);//true
//
//       // 三、使用Iterator接口中的方法next取出集合中的下一个元素
//        String s=it.next();
//        System.out.println(s);
//
//        //二、使用Iterator接口中的方法hasNext判断还有没有下一个元素
//        b=it.hasNext();
//        System.out.println(b);//true
//        // 三、使用Iterator接口中的方法next取出集合中的下一个元素
//        s=it.next();
//        System.out.println(s);
//        二、使用Iterator接口中的方法hasNext判断还有没有下一个元素
//        b=it.hasNext();
//        System.out.println(b);//true
//        // 三、使用Iterator接口中的方法next取出集合中的下一个元素
//        s=it.next();
//        System.out.println(s);
//        二、使用Iterator接口中的方法hasNext判断还有没有下一个元素
//        b=it.hasNext();
//        System.out.println(b);//true
//        // 三、使用Iterator接口中的方法next取出集合中的下一个元素
//        s=it.next();
//        System.out.println(s);
//        
//          b=it.hasNext();
        System.out.println(b);没有元素,返回false
        // 三、使用Iterator接口中的方法next取出集合中的下一个元素
        s=it.next();没有元素,在取出元素会抛出NoSuchElementException没有元素异常
        System.out.println(s);
    }
}

Iterator(迭代器)实现原理

这里咱们来看看Java里AbstractList实现Iterator的源代码:this

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // List接口实现了Collection<E>, Iterable<E> 

    protected AbstractList() {  
    }     
    public Iterator<E> iterator() {  
    return new Itr();  // 这里返回一个迭代器    }  

    private class Itr implements Iterator<E> {  // 内部类Itr实现迭代器

    int cursor = 0;  
    int lastRet = -1;  
    int expectedModCount = modCount;  

    public boolean hasNext() {  // 实现hasNext方法
            return cursor != size();  
    }  

    public E next() {  // 实现next方法
            checkForComodification();  
        try {  
        E next = get(cursor);  
        lastRet = cursor++;  
        return next;  
        } catch (IndexOutOfBoundsException e) {  
        checkForComodification();  
        throw new NoSuchElementException();  
        }  
    }  

    public void remove() {  // 实现remove方法
        if (lastRet == -1)  
        throw new IllegalStateException();  
            checkForComodification();  

        try {  
        AbstractList.this.remove(lastRet);  
        if (lastRet < cursor)  
            cursor--;  
        lastRet = -1;  
        expectedModCount = modCount;  
        } catch (IndexOutOfBoundsException e) {  
        throw new ConcurrentModificationException();  
        }  
    }   
    final void checkForComodification() {  
        if (modCount != expectedModCount)  
        throw new ConcurrentModificationException();  
    }  
    }  
}

能够看到,实现next()是经过get(cursor),而后cursor++,经过这样实现遍历。code

这部分代码不难看懂,惟一难懂的是remove操做里涉及到的expectedModCount = modCount;对象

在网上查到说这是集合迭代中的一种“快速失败”机制,这种机制提供迭代过程当中集合的安全性。接口

从源代码里能够看到增删操做都会使modCount++,经过和expectedModCount的对比,迭代器能够快速的知道迭代过程当中是否存在list.add()相似的操做,存在的话快速失败!
在第一个例子基础上添加一条语句:

import java.util.*;
public class Muster {

    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        Iterator it = list.iterator();
        while(it.hasNext()){
            String str = (String) it.next();
            System.out.println(str);
            list.add("s");        //添加一个add方法
        }
    }
}

运行结果:

a
Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
  at java.util.ArrayList$Itr.next(Unknown Source)
  at com.hasse.Muster.main(Muster.java:11)

这就会抛出一个下面的异常,迭代终止。

加强for循环

加强for循环的做用: 简化迭代器的书写格式。(注意:加强for循环的底层仍是使用了迭代器遍历。)
加强for循环的适用范围: 若是是实现了Iterable接口的对象或者是数组对象均可以使用加强for循环。
加强for循环的缺点:加强for循环和iterator遍历的效果是同样的,也就说加强for循环的内部也就是调用iteratoer实现的,可是加强for循环有些缺点,例如不能在加强循环里动态的删除集合内容、不能获取下标等。

加强for循环的格式:

for(数据类型 变量名 :遍历的目标){
        //数据类型 变量名:声明一个变量用来接收遍历目标遍历后的元素
}

加强for循环要注意的事项:

  1. 加强for循环底层也是使用了迭代器获取的,只不过获取迭代器由jvm完成,不须要咱们获取迭代器而已,因此在使用加强for循环变量元素的过程当中不许使用集合对象对集合的元素个数进行修改。
  2. 迭代器遍历元素与加强for循环变量元素的区别:使用迭代器遍历集合的元素时能够删除集合的元素,而加强for循环变量集合的元素时,不能调用迭代器的remove方法删 除 元素。
  3. 普通for循环与加强for循环的区别:普通for循环能够没有遍历的目标,而加强for循环必定要有遍历的目标。
int[] arr = {5,11,2,4,9,18}; 

        普通for循环的遍历方式 
        for(int i =  0 ; i<arr.length ; i++){ 
            System.out.println("元素:"+ arr[i]); 
        } 

        //使用加强for循环实现 
        for(int item :arr){ 
            System.out.println("元素:"+ item); 
        }
HashSet<String> set = new HashSet<String>();  
        //添加元素  
        set.add("张狗蛋");  
        set.add("张全蛋");  
        set.add("张傻蛋");  

        //使用迭代器遍历Set的集合. 
        Iterator<String> it  = set.iterator(); 
        while(it.hasNext()){ 
            String temp = it.next(); 
            System.out.println("元素:"+ temp); 
            it.remove(); 
        } 

        //使用加强for循环解决 
        for(String item : set){ 
            System.out.println("元素:"+ item); 

        }

注意: Map集合没有实现Iterable接口,因此map集合不能直接使用加强for循环,若是须要使用加强for循环须要借助于Collection的集合。

HashMap<String, String> map = new HashMap<String, String>();  
        map.put("01","甲");  
        map.put("02","乙");  
        map.put("03","丙");  
        map.put("04","丁");  
        Set<Map.Entry<String, String>> entrys = map.entrySet();  
        for(Map.Entry<String, String> entry  :entrys){  
            System.out.println("键:"+ entry.getKey()+" 值:"+ entry.getValue());  
        }
相关文章
相关标签/搜索