增強型for循環與集合


在python中對可迭代對象實現了__iter__方法。只要一個對象實現了__iter__方法,並返回一個迭代器,這個對象就是可迭代對象,就可以用for對其迭代。每次迭代的時候會調用迭代器__next__方法。在python中寫如下代碼

class A:
    def __iter__(self):
        print('.....iter........')
        return (i for i in ['1',2,4,'python','java',"c"] if type(i)==str)
a = A()
for i in a:
    print(i)

觀察運行結果

會看到先輸出了.....iter........,這是因為遇到for時python解釋器會自動調用對象的__iter__方法,因此會看到該行輸出

在java中是否有相同的概念?先看這一段代碼

在代碼中for語句加上斷點。運行跟蹤代碼,執行到斷點時發現果然跳到了LinkedList父類里面的iterator方法里面,在父類AbstractSequentialList方法里有調用了listIterator方法,接着到了LinkedList的自己中的listIterator方法

這樣看來java中也有相同的概念,遇到for時jvm自動調用對象的iterator方法,該方法返回一個迭代器(實現了java.util.Iterator接口的都是迭代器),每一次迭代都會調用該迭代器的next方法。

在LinkedList的listIterator方法中返回的是一個ListItr對象,這個對象其父類是一個ListIterator,ListIterator又繼承 Iterator接口,因此ListItr是一個迭代器對象會有next方法。

查看iterator接口時發現這個接口沒有iterator方法,那遇到for時jvm自動調用的誰itorator方法?查看LinkedList的一系列父類最終發現其超父類Collection里面有一個itorator方法

而Collection又繼承了Iterable接口。

因此一個對象要能進行迭代必須實現Iterable接口(告訴jvm該類是能迭代的),重寫iterator方法,並且在該方法返回一個Iterator的實現

package cn.itcast.jdk15;
 
import java.util.Iterator;
 
//自定一個類使用增強for循環
class MyList implements Iterable<String>{
    
    Object[] arr = new Object[10];
    
    int index = 0 ;    //當前的指針
    
    public void add(Object o){
        arr[index++] = o;  // 1
    }
    
    public int size(){
        return index;
    }
 
    @Override
    public Iterator<String> iterator() {
        
        
        return new Iterator<String>() {
 
            int cursor  = 0;
 
            @Override
            public boolean hasNext() {
                return cursor<index;
            }
 
            @Override
            public String next() {
                return (String) arr[cursor++];
            }
 
            @Override
            public void remove() {
                
            }
        };
    }
}
 
public class Demo3 {
    
    public static void main(String[] args) {
        MyList list = new MyList();
        list.add("張三");
        list.add("李四");
        list.add("王五");
        
        for(String item :list){
            System.out.println(item);
        }
        
        
        
    }
    
}

在遍歷HashMap的時候你想過為什么不能直接寫這樣的代碼嗎?

原因就是map和其超父類沒有任何一個與Iterable接口有關系,map是不可直接迭代的,因為其本身或其超父類都沒有實現或繼承Iterable接口

到這你可以寫一個類繼承HashMap同時讓這個類實現java.util.Iterable接口,改寫HashMap,使其能夠直接迭代,代碼如下

import java.util.*;
public class MyHashMap<K,V> extends HashMap<K,V> implements Iterable {
    @Override
    public Iterator iterator() {
        return entrySet().iterator();
//        return getIterator();
    }

//    private Iterator getIterator(){
//        return new mapIterator();
//    }

    /**
     * 很多屬性由於是默認訪問權限,子類獲取不到,因此該方式不可行
     *
     */
//    private  final class mapIterator<E> implements Iterator<E>{
//        Entry<K,V> next;        // next entry to return
//        int expectedModCount;   // For fast-fail
//        int index;              // current slot
//        Entry<K,V> current;     // current entry
//
//        mapIterator() {
//            expectedModCount = modCount;
//            if (size > 0) { // advance to first entry
//                Entry[] t = table;
//                while (index < t.length && (next = t[index++]) == null)
//                    ;
//            }
//        }
//
//        public final boolean hasNext() {
//            return next != null;
//        }
//
//        final Entry<K,V> nextEntry() {
//            if (modCount != expectedModCount)
//                throw new ConcurrentModificationException();
//            Entry<K,V> e = next;
//            if (e == null)
//                throw new NoSuchElementException();
//
//            if ((next = e.next) == null) {
//                Entry[] t = table;
//                while (index < t.length && (next = t[index++]) == null)
//                    ;
//            }
//            current = e;
//            return e;
//        }
//        public Map.Entry<K,V> next() {
//            return nextEntry();
//        }
//
//    }

    public static void main(String[]args){
        MyHashMap<String,String> map = new MyHashMap<>();
        map.put("aa","a");
        map.put("bb","b");
        System.out.println(map.get("aa"));
        for(Object obj:map){
            Map.Entry<String,String> e= (Map.Entry<String,String>)(obj);
            System.out.println(e.getKey()+":"+e.getValue());
        }

    }
}

 增強型for循環與集合

集合類主要分為兩大類:Collection和Map

collection繼承了Itarable接口,collection的實現類都是可直接迭代的

Map沒有實現Itarable接口,其實現類不可以直接迭代


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM