小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Java迭代 : Iterator和Iterable接口

 Levy_X 2017-05-26

從英文意思去理解


 


Iterable :故名思議,實(shí)現(xiàn)了這個(gè)接口的集合對(duì)象支持迭代,是可迭代的。able結(jié)尾的表示 能...樣,可以做...。

Iterator:   在英語(yǔ)中or 結(jié)尾是都是表示 ...樣的人 or ... 者。如creator就是創(chuàng)作者的意思。這里也是一樣:iterator就是迭代者,我們一般叫迭代器,它就是提供迭代機(jī)制的對(duì)象,具體如何迭代,都是Iterator接口規(guī)范的。




Iterable


一個(gè)集合對(duì)象要表明自己支持迭代,能有使用foreach語(yǔ)句的特權(quán),就必須實(shí)現(xiàn)Iterable接口,表明我是可迭代的!然而實(shí)現(xiàn)Iterable接口,就必需為foreach語(yǔ)句提供一個(gè)迭代器。

這個(gè)迭代器是用接口定義的 iterator方法提供的。也就是iterator方法需要返回一個(gè)Iterator對(duì)象。

 foreach只能用于數(shù)組和實(shí)現(xiàn)了Iterable接口的類(lèi)


 


復(fù)制代碼

//Iterable JDK源碼
//可以通過(guò)成員內(nèi)部類(lèi),方法內(nèi)部類(lèi),甚至匿名內(nèi)部類(lèi)去實(shí)現(xiàn)Iterator

public
interface Iterable<T> { Iterator<T> iterator(); }

復(fù)制代碼

 


 


Iterator


 包含3個(gè)方法: hasNext ,  next , remove。remove按需求實(shí)現(xiàn),一般它很少用到,以至于Eclipse接口方法自動(dòng)補(bǔ)全時(shí),都忽略了remove放方法。


1、每次在迭代前   ,先調(diào)用hasNext()探測(cè)是否迭代到終點(diǎn)(本次還能再迭代嗎?)。

2、next方法不僅要返回當(dāng)前元素,還要后移游標(biāo)cursor

3、remove()方法用來(lái)刪除最近一次已經(jīng)迭代出的元素


4、 迭代出的元素是原集合中元素的拷貝(重要)

5、配合foreach使用


 


復(fù)制代碼

//Iterator接口的JDK源碼,注釋為整理建議使用Iterator的正確姿勢(shì)

public
interface Iterator<E> { boolean hasNext(); //每次next之前,先調(diào)用此方法探測(cè)是否迭代到終點(diǎn) E next(); //返回當(dāng)前迭代元素 ,同時(shí),迭代游標(biāo)后移 /*刪除最近一次已近迭代出出去的那個(gè)元素。 只有當(dāng)next執(zhí)行完后,才能調(diào)用remove函數(shù)。 比如你要?jiǎng)h除第一個(gè)元素,不能直接調(diào)用 remove() 而要先next一下( ); 在沒(méi)有先調(diào)用next 就調(diào)用remove方法是會(huì)拋出異常的。 這個(gè)和MySQL中的ResultSet很類(lèi)似 */ void remove()
{
throw new UnsupportedOperationException("remove"); } }

復(fù)制代碼

 


 


 


 迭代的具體細(xì)節(jié)


需要理解的地方


1、hasNext , next  , remove 的調(diào)用順序


2、迭代出來(lái)的是原集合元素拷貝!


 


下面是手動(dòng)迭代的例子,foreach的原理和它一樣。


復(fù)制代碼

public static void main(String[] args)
{

        List<Integer> li = new ArrayList<>();
        
        li.add(1);
        li.add(2);
        li.add(3);
        
//不使用foreach 而手動(dòng)迭代 Iterator
<Integer> iter = li.iterator(); //獲取ArrayList 的迭代器 while(iter.hasNext()) //①先探測(cè)能否繼續(xù)迭代 { System.out.println(iter.next()); //②后取出本次迭代出的元素 //invoke remove() //③最后如果需要,調(diào)用remove } }

復(fù)制代碼

 


 


AbstractList中實(shí)現(xiàn)的迭代器類(lèi),可以借鑒參考。


我們實(shí)現(xiàn)自己的迭代器的情況很少,畢竟JDK集合足夠強(qiáng)大。


源碼中有一些保護(hù)機(jī)制,為了便于理解我刪改了。


復(fù)制代碼

private class Itr implements Iterator<E> 
{ /*
AbstractList 中實(shí)現(xiàn)的迭代器,刪除了一些細(xì)節(jié)。不影響理解
Itr為一個(gè)priavate成員內(nèi)部類(lèi)

*/
int cursor = 0; //馬上等待被迭代元素的index //最近一次,已經(jīng)被迭代出的元素的index,如果這個(gè)元素迭代后,被刪除了,則lastRet重置為-1 int lastRet = -1; public boolean hasNext() { return cursor != size(); //當(dāng)前游標(biāo)值 等于 集合的size() 說(shuō)明已經(jīng)不能再迭代了。 } public E next() { int i = cursor; E next = get(i); lastRet = i; //lastRet 保存的是最近一次已經(jīng)被迭代出去的元素索引 cursor = i + 1; //cursor為馬上等待被迭代的元素的索引 return next; } public void remove() { if (lastRet < 0) //調(diào)用remove之前沒(méi)有調(diào)用next throw new IllegalStateException(); //則拋異常。這就是為什么在使用remove前,要next的原因 OuterList.this.remove(lastRet); //從集合中刪除這個(gè)元素 if (lastRet < cursor) //集合刪除元素后,集合后面的元素的索引會(huì)都減小1,cursor也要同步后移 cursor--; lastRet = -1; //重置 } }

復(fù)制代碼

 


 


 


迭代出來(lái)的元素都是原來(lái)集合元素的拷貝


Java集合中保存的元素實(shí)質(zhì)是對(duì)象的引用(可以理解為C中的指針),而非對(duì)象本身。


迭代出的元素也就都是 引用的拷貝,結(jié)果還是引用。那么,如果集合中保存的元素是可變類(lèi)型的,我們就可以通過(guò)迭代出的元素修改原集合中的對(duì)象。


而對(duì)于不可變類(lèi)型,如String  基本元素的包裝類(lèi)型Integer 都是則不會(huì)反應(yīng)到原集合中。


 


為了便于理解,畫(huà)張圖:


 


         


 


 


 


驗(yàn)證代碼:


 


復(fù)制代碼

public class Main
{

    public static void main(String[] args)
    {

        List<Person> li = new ArrayList<>();
        
        Person p = new Person("Tom");
        
        li.add(p);
        
        
        for(Person ap: li)
        {
            ap.setName("Jerry");
        }
        
        System.out.println(li.get(0).getName());     //Jerry  not Tom
        

    }

}


class Person
{
    
    public Person(String name)
    {
        this.name = (name==null?"":name);
        
    }
    
    private  String name;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        if(name == null)
             name = "";
        this.name = name;
    }
    
}

復(fù)制代碼

 


 


 


 


小試牛刀,讓自己的類(lèi)支持迭代。


復(fù)制代碼

public class Main
{

    public static void main(String[] args)
    {


        MyString s = new MyString("1234567");
        
        
        for(char c:s)
        {
            System.out.println(c);
        }

        

    }

}




class MyString implements Iterable<Character>
{
    
    private int length = 0;
    private String ineers = null;
    
    public MyString(String s)
    {
        this.ineers = s;
        this.length = s.length();
        
    }
    
    
    @Override
    public Iterator<Character> iterator()
    {
        
        
        class iter  implements Iterator<Character>     //方法內(nèi)部類(lèi)
        {
            private int cur= 0;
            
            
            @Override
            public boolean hasNext()
            {
                return cur != length;
            }

            @Override
            public Character next()
            {
                
                Character c = ineers.charAt(cur);
                cur++;
                return c;
            }
            
            public void remove()
            {
                 // do nothing 
                
            }

        }
        return new iter();     //安裝Iterable接口的約定,返回迭代器
                   
    }
    
}

復(fù)制代碼

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多