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(數據類型 變量名 :遍歷的目標){ //數據類型 變量名:聲明一個變量用來接收遍歷目標遍歷後的元素 }
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()); }