[轉載]Java迭代器(iterator詳解以及和for循環的區別)

Java迭代器(iterator詳解以及和for循環的區別)

以爲有用的話,歡迎一塊兒討論相互學習~

個人微博個人github個人B站

前言

  • 迭代器是一種模式、詳細可見其設計模式,可使得序列類型的數據結構的遍歷行爲與被遍歷的對象分離,即咱們無需關心該序列的底層結構是什麼樣子的。只要拿到這個對象,使用迭代器就能夠遍歷這個對象的內部
  • Iterable 實現這個接口的集合對象支持迭代,是能夠迭代的。實現了這個能夠配合foreach使用~
  • Iterator 迭代器,提供迭代機制的對象,具體如何迭代是這個Iterator接口規範的。
//Iterable JDK源碼
//能夠經過成員內部類,方法內部類,甚至匿名內部類去實現Iterator

public interface Iterable<T>
{

    Iterator<T> iterator();
  • Iterable還有一個默認的方法forEach()
  • 而Iterator接口:包含三個方法:hasNext,next,remove、remove通常不多用到.
public interface Iterator<E> {


    boolean hasNext();    //每次next以前,先調用此方法探測是否迭代到終點

    E next();            //返回當前迭代元素 ,同時,迭代遊標後移


     /*刪除最近一次已近迭代出出去的那個元素。
     只有當next執行完後,才能調用remove函數。
     好比你要刪除第一個元素,不能直接調用 remove()   而要先next一下( );
     在沒有先調用next 就調用remove方法是會拋出異常的。
     這個和MySQL中的ResultSet很相似
    */
    void remove()
    {
        throw new UnsupportedOperationException("remove");
    }

Note

  • 迭代出來的元素都是原來集合元素的拷貝。
  • Java集合中保存的元素實質是對象的引用,而非對象自己。
  • 迭代出的對象也是引用的拷貝,結果仍是引用。那麼若是集合中保存的元素是可變類型的,那麼能夠經過迭代出的元素修改原集合中的對象。
import java.util.ArrayList;
import java.util.Iterator;

public class test {
    public static void main(String[] args) {
        ArrayList<Person> array = new ArrayList<Person>();

        Person p1 = new Person("Tom1");
        Person p2 = new Person("Tom2");
        Person p3 = new Person("Tom3");
        Person p4 = new Person("Tom4");

        array.add(p1);
        array.add(p2);
        array.add(p3);
        array.add(p4);

        Iterator<Person> iterator = array.iterator();

        for (Person pp : array){
            System.out.println(pp.getName());
        }

        System.out.println("\r\n" + "-----利用Lambda表達式的foreach-----" + "\r\n");
        array.forEach(obj -> System.out.println(obj.getName()));


        System.out.println("\r\n" + "-----利用for循環-----" + "\r\n");
        for(Person p : array){
            p.setName("wang");
        }

        while(iterator.hasNext()){
            System.out.println(iterator.next().getName()); //輸出的是wang,而不是tom
        }



    }
}

Map遍歷也是同樣的~

public static void main(String[] args) {
        Map map = new HashMap();
        for(int i = 0; i < 10; i ++){
            map.put(i, String.valueOf("map" + i));
        }
        Iterator iterMap = map.entrySet().iterator();
        while(iterMap.hasNext()){
            Map.Entry strMap = (Map.Entry)iterMap.next();
            System.out.println("key爲:" + strMap.getKey() +
                    ", value爲:" + strMap.getValue());
        }
    }

那麼當Iterator迭代訪問Collection集合中元素時,Collection的元素不能改變(多個線程的修改),只有經過Iterator的remove()方法刪除上一次next()方法返回集合才能夠。這樣會引起ModificationException異常,即fail-fast機制java

//建立集合,添加元素和上述同樣      
        Iterator<Person> iterator = array.iterator();

      while(iterator.hasNext()){
         String name = iterator.next().getName();
         System.out.println(name);
         if(name.equals("Tom3")){
             //array.remove(name);  不推薦這種方式
             iterator.remove();
         }
      }

Iterator與泛型搭配:

  • Iterator對集合類中的任何一個實現類,均可以返回這樣一個Iterator對象。能夠適用於任何一個類。
  • 由於集合類(List和Set等)能夠裝入的對象的類型是不肯定的,從集合中取出時都是Object類型,用時都須要進行強制轉化,這樣會很麻煩,用上泛型,就是提早告訴集合肯定要裝入集合的類型,這樣就能夠直接使用而不用顯示類型轉換.很是方便.

foreach和Iterator的關係:

  • for each以用來處理集合中的每一個元素而不用考慮集合定下標。就是爲了讓用Iterator簡單。可是刪除的時候,區別就是在remove,循環中調用集合remove會致使原集合變化致使錯誤,而應該用迭代器的remove方法。

使用for循環仍是迭代器Iterator對比

  • 採用ArrayList對隨機訪問比較快,而for循環中的get()方法,採用的便是隨機訪問的方法,所以在ArrayList裏,for循環較快
  • 採用LinkedList則是順序訪問比較快,iterator中的next()方法,採用的便是順序訪問的方法,所以在LinkedList裏,使用iterator較快
  • 從數據結構角度分析,for循環適合訪問順序結構,能夠根據下標快速獲取指定元素.而Iterator 適合訪問鏈式結構,由於迭代器是經過next()和Pre()來定位的.能夠訪問沒有順序的集合.
  • 而使用 Iterator 的好處在於可使用相同方式去遍歷集合中元素,而不用考慮集合類的內部實現(只要它實現了 java.lang.Iterable 接口),若是使用 Iterator 來遍歷集合中元素,一旦再也不使用 List 轉而使用 Set 來組織數據,那遍歷元素的代碼不用作任何修改,若是使用 for 來遍歷,那全部遍歷此集合的算法都得作相應調整,由於List有序,Set無序,結構不一樣,他們的訪問算法也不同.(仍是說明了一點遍歷和集合自己分離了)
相關文章
相關標籤/搜索