迭代器和加強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());  
        }
相關文章
相關標籤/搜索