欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JAVA中的for-each循環(huán)與迭代

 更新時(shí)間:2016年10月24日 14:22:40   作者:知其然,后知其所以然  
本文詳解了JAVA中的for-each循環(huán)與迭代,是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),也是java中的難點(diǎn)知識(shí),需要的朋友可以參考下 。

在學(xué)習(xí)java中的collection時(shí)注意到,collection層次的根接口Collection實(shí)現(xiàn)了Iterable<T>接口(位于java.lang包中),實(shí)現(xiàn)這個(gè)接口允許對(duì)象成為 "foreach" 語(yǔ)句的目標(biāo),而此接口中的唯一方法,實(shí)現(xiàn)的就是返回一個(gè)在一組 T 類型的元素上進(jìn)行迭代的迭代器。

一、迭代器Iterator

接口:Iterator<T>

public interface Iterator<E>{
  boolean hasNext(); 
 E next(); 
 void remove();
 }

查看Iterator接口API可以知道,這是對(duì)collection進(jìn)行迭代的迭代器。迭代器允許調(diào)用者利用定義良好的語(yǔ)義在迭代期間從迭代器所指向的 collection 移除元素。

尤其值得注意的是此迭代器remove()方法的使用:從迭代器指向的 collection 中移除迭代器返回的最后一個(gè)元素(可選操作)。每次調(diào)用 next 只能調(diào)用一次此方法。如果進(jìn)行迭代時(shí)用調(diào)用此方法(remove方法)之外的其他方式修改了該迭代器所指向的 collection,則迭代器的行為是不確定的。 接口設(shè)計(jì)人員在設(shè)計(jì)Iterator<T>接口的時(shí)候已經(jīng)指出,在進(jìn)行迭代時(shí)如果調(diào)用了除了迭代器的remove()方法修改了該迭代器所指向的collection,則會(huì)造成不確定的后果。具體出現(xiàn)什么后果依迭代器的具體實(shí)現(xiàn)而定。針對(duì)這種不確定的后果可能出現(xiàn)的情況,在學(xué)習(xí)ArrayList時(shí)遇到了其中一種:迭代器拋出 ConcurrentModificationException異常。具體異常情況如下代碼所示:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class ItaratorTest {

  public static void main(String[] args) {
    Collection<String> list = new ArrayList<String>();
    list.add("Android");
    list.add("IOS");
    list.add("Windows Mobile");

    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
      String lang = iterator.next();
      list.remove(lang);//will throw ConcurrentModificationException
    }
  }

}

此段代碼在運(yùn)行時(shí)會(huì)拋出ConcurrentModificationException異常,因?yàn)槲覀冊(cè)诘鬟\(yùn)行期間沒有用iterator的remove()方法來刪除元素,而是使用ArrayList的 remove()方法改變了迭代器所指向的collection。這就違反了迭代器的設(shè)計(jì)原則,所以發(fā)生了異常。

所報(bào)異常情況如下所示:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at Text.ItaratorTest.main(ItaratorTest.java:17)

二、for-each循環(huán)與迭代器Iterator<T>

從Java5起,在Java中有了for-each循環(huán),可以用來循環(huán)遍歷collection和array。Foreach循環(huán)允許你在無需保持傳統(tǒng)for循環(huán)中的索引,或在使用iterator /ListIterator(ArrayList中的一種迭代器實(shí)現(xiàn))時(shí)無需調(diào)用while循環(huán)中的hasNext()方法就能遍歷collection。for-each循環(huán)簡(jiǎn)化了任何Collection或array的遍歷過程。但是使用foreach循環(huán)也有兩點(diǎn)需要注意。

使用foreach循環(huán)的對(duì)象,必須實(shí)現(xiàn)了Iterable<T>接口

請(qǐng)看如下示例:

import java.util.ArrayList;

public class ForeachTest1 {

  public static void main(String args[]) {
    CustomCollection<String> myCollection = new CustomCollection<String>();
    myCollection.add("Java");
    myCollection.add("Scala");
    myCollection.add("Groovy");

    // What does this code will do, print language, throw exception or
    // compile time error
    for (String language : myCollection) {
      System.out.println(language);
    }
  }

  private class CustomCollection<T> {
    private ArrayList<T> bucket;

    public CustomCollection() {
      bucket = new ArrayList();
    }

    public int size() {
      return bucket.size();
    }

    public boolean isEmpty() {
      return bucket.isEmpty();
    }

    public boolean contains(T o) {
      return bucket.contains(o);
    }

    public boolean add(T e) {
      return bucket.add(e);
    }

    public boolean remove(T o) {
      return bucket.remove(o);
    }

  }
}

上述代碼將無法通過編譯,這是因?yàn)榇a中的CustomCollection類沒有實(shí)現(xiàn)Iterable<T>接口,編譯期的報(bào)錯(cuò)如下:

Exception in thread "main" java.lang.Error: Unresolved compilation problem:
    Can only iterate over an array or an instance of java.lang.Iterable

    at Text.ForeachTest1.main(ForeachTest1.java:15)

事實(shí)上,無需等到編譯時(shí)才發(fā)現(xiàn)報(bào)錯(cuò),eclipse會(huì)在這段代碼寫完之后就會(huì)在foreach循環(huán)處顯示錯(cuò)誤:Can only iterate over an array or an instance of java.lang.Iterable

從上述示例可以再次得到確認(rèn)的是,foreach循環(huán)只適用于實(shí)現(xiàn)了Iterable<T>接口的對(duì)象。由于所有內(nèi)置Collection類都實(shí)現(xiàn)了java.util.Collection接口,已經(jīng)繼承了Iterable,所以為了解決上述問題,可以選擇簡(jiǎn)單地讓CustomCollection實(shí)現(xiàn)Collection接口或者繼承AbstractCollection。解決方式如下:

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Iterator;

public class ForeachTest {
  public static void main(String args[]) {
    CustomCollection<String> myCollection = new CustomCollection<String>();
    myCollection.add("Java");
    myCollection.add("Scala");
    myCollection.add("Groovy");
    for (String language : myCollection) {
      System.out.println(language);
    }
  }

  private static class CustomCollection<T> extends AbstractCollection<T> {
    private ArrayList<T> bucket;

    public CustomCollection() {
      bucket = new ArrayList();
    }

    public int size() {
      return bucket.size();
    }

    public boolean isEmpty() {
      return bucket.isEmpty();
    }

    public boolean contains(Object o) {
      return bucket.contains(o);
    }

    public boolean add(T e) {
      return bucket.add(e);
    }

    public boolean remove(Object o) {
      return bucket.remove(o);
    }

    @Override
    public Iterator<T> iterator() {
      // TODO Auto-generated method stub
      return bucket.iterator();
    }
  }
}

2.foreach循環(huán)的內(nèi)部實(shí)現(xiàn)也是依靠Iterator進(jìn)行實(shí)現(xiàn)的

為了驗(yàn)證foreach循環(huán)是使用Iterator作為內(nèi)部實(shí)現(xiàn)這一事實(shí),我們依然采用本文最開始的實(shí)例進(jìn)行驗(yàn)證:

public class ItaratorTest {

  public static void main(String[] args) {
    Collection<String> list = new ArrayList<String>();
    list.add("Android");
    list.add("IOS");
    list.add("Windows Mobile");

    // example1
    // Iterator<String> iterator = list.iterator();
    // while (iterator.hasNext()) {
    // String lang = iterator.next();
    // list.remove(lang);
    // }

    // example 2
    for (String language : list) {
      list.remove(language);
    }
  }

}

程序運(yùn)行時(shí)所報(bào)異常:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at Text.ItaratorTest.main(ItaratorTest.java:22)

此異常正說明了for-each循環(huán)內(nèi)部使用了Iterator來遍歷Collection,它也調(diào)用了Iterator.next(),這會(huì)檢查(元素的)變化并拋出ConcurrentModificationException。

總結(jié):

  • 在遍歷collection時(shí),如果要在遍歷期間修改collection,則必須通過Iterator/listIterator來實(shí)現(xiàn),否則可能會(huì)發(fā)生“不確定的后果”。
  • foreach循環(huán)通過iterator實(shí)現(xiàn),使用foreach循環(huán)的對(duì)象必須實(shí)現(xiàn)Iterable接口

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java的CGLIB動(dòng)態(tài)代理深入解析

    Java的CGLIB動(dòng)態(tài)代理深入解析

    這篇文章主要介紹了Java的CGLIB動(dòng)態(tài)代理深入解析,CGLIB是強(qiáng)大的、高性能的代碼生成庫(kù),被廣泛應(yīng)用于AOP框架,它底層使用ASM來操作字節(jié)碼生成新的類,為對(duì)象引入間接級(jí)別,以控制對(duì)象的訪問,需要的朋友可以參考下
    2023-11-11
  • SpringBoot整合MinIO實(shí)現(xiàn)文件存儲(chǔ)系統(tǒng)的代碼示例

    SpringBoot整合MinIO實(shí)現(xiàn)文件存儲(chǔ)系統(tǒng)的代碼示例

    在現(xiàn)代的應(yīng)用程序中,文件存儲(chǔ)和管理是一個(gè)常見的需求,MinIO是一個(gè)開源的對(duì)象存儲(chǔ)系統(tǒng),與Spring?Boot框架結(jié)合使用,可以快速構(gòu)建高性能的文件存儲(chǔ)系統(tǒng),本文將介紹如何使用Spring?Boot和MinIO來實(shí)現(xiàn)文件存儲(chǔ)系統(tǒng)
    2023-06-06
  • Java的Spring?AOP詳細(xì)講解

    Java的Spring?AOP詳細(xì)講解

    章主要為大家詳細(xì)介紹了Java的Spring?AOP,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • java基于GUI實(shí)現(xiàn)簡(jiǎn)單畫筆小畫板

    java基于GUI實(shí)現(xiàn)簡(jiǎn)單畫筆小畫板

    這篇文章主要為大家詳細(xì)介紹了java基于GUI實(shí)現(xiàn)簡(jiǎn)單畫筆小畫板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 記錄一次connection reset 錯(cuò)誤的解決全過程

    記錄一次connection reset 錯(cuò)誤的解決全過程

    這篇文章主要介紹了記錄一次connection reset 錯(cuò)誤的解決全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 探討:使用httpClient在客戶端與服務(wù)器端傳輸對(duì)象參數(shù)的詳解

    探討:使用httpClient在客戶端與服務(wù)器端傳輸對(duì)象參數(shù)的詳解

    本篇文章是對(duì)使用httpClient在客戶端與服務(wù)器端傳輸對(duì)象參數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)流程詳解

    SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)流程詳解

    ShedLock是一個(gè)鎖,官方解釋是他永遠(yuǎn)只是一個(gè)鎖,并非是一個(gè)分布式任務(wù)調(diào)度器。一般shedLock被使用的場(chǎng)景是,你有個(gè)任務(wù),你只希望他在單個(gè)節(jié)點(diǎn)執(zhí)行,而不希望他并行執(zhí)行,而且這個(gè)任務(wù)是支持重復(fù)執(zhí)行的
    2023-02-02
  • java實(shí)現(xiàn)歸并排序算法

    java實(shí)現(xiàn)歸并排序算法

    歸并排序:是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。 本文我們就來詳細(xì)的探討下。
    2015-04-04
  • SpringBoot實(shí)現(xiàn)配置文件的替換

    SpringBoot實(shí)現(xiàn)配置文件的替換

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)配置文件的替換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java用兩個(gè)例子充分闡述多態(tài)的可拓展性介紹

    java用兩個(gè)例子充分闡述多態(tài)的可拓展性介紹

    下面小編就為大家?guī)硪黄猨ava用兩個(gè)例子充分闡述多態(tài)的可拓展性介紹。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06

最新評(píng)論