一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 詳解JAVA中的for-each循環與迭代

詳解JAVA中的for-each循環與迭代

2020-06-27 12:48知其然,后知其所以然 JAVA教程

本文詳解了JAVA中的for-each循環與迭代,是JS入門學習中的基礎知識,也是java中的難點知識,需要的朋友可以參考下 。

在學習java中的collection時注意到,collection層次的根接口Collection實現了Iterable<T>接口(位于java.lang包中),實現這個接口允許對象成為 "foreach" 語句的目標,而此接口中的唯一方法,實現的就是返回一個在一組 T 類型的元素上進行迭代的迭代器。

一、迭代器Iterator

接口:Iterator<T>

?
1
2
3
4
5
public interface Iterator<E>{
  boolean hasNext();
 E next();
 void remove();
 }

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
    }
  }
 
}

此段代碼在運行時會拋出ConcurrentModificationException異常,因為我們在迭代器運行期間沒有用iterator的remove()方法來刪除元素,而是使用ArrayList的 remove()方法改變了迭代器所指向的collection。這就違反了迭代器的設計原則,所以發生了異常。

所報異常情況如下所示:

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循環與迭代器Iterator<T>

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

使用foreach循環的對象,必須實現了Iterable<T>接口

請看如下示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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);
    }
 
  }
}

上述代碼將無法通過編譯,這是因為代碼中的CustomCollection類沒有實現Iterable<T>接口,編譯期的報錯如下:

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)

事實上,無需等到編譯時才發現報錯,eclipse會在這段代碼寫完之后就會在foreach循環處顯示錯誤:Can only iterate over an array or an instance of java.lang.Iterable

從上述示例可以再次得到確認的是,foreach循環只適用于實現了Iterable<T>接口的對象。由于所有內置Collection類都實現了java.util.Collection接口,已經繼承了Iterable,所以為了解決上述問題,可以選擇簡單地讓CustomCollection實現Collection接口或者繼承AbstractCollection。解決方式如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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循環的內部實現也是依靠Iterator進行實現的

為了驗證foreach循環是使用Iterator作為內部實現這一事實,我們依然采用本文最開始的實例進行驗證:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);
    }
  }
 
}

程序運行時所報異常:

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循環內部使用了Iterator來遍歷Collection,它也調用了Iterator.next(),這會檢查(元素的)變化并拋出ConcurrentModificationException。

總結:

  • 在遍歷collection時,如果要在遍歷期間修改collection,則必須通過Iterator/listIterator來實現,否則可能會發生“不確定的后果”。
  • foreach循環通過iterator實現,使用foreach循環的對象必須實現Iterable接口

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美成a人片免费看久久 | 国产精品久久久久久久久免费 | ai换脸杨颖被啪在线观看 | 亚洲+欧美+国产+综合 | 精品国产免费第一区二区 | 欧美美女被艹 | 国产精品亚洲精品青青青 | 青草福利在线 | 国产女主播在线播放一区二区 | 91短视频社区在线观看 | 免费一级毛片完整版在线看 | 国产va免费精品高清在线观看 | 青青草原手机在线视频 | 国产精品思瑞在线观看 | 草莓香蕉榴莲丝瓜秋葵绿巨人在线看 | 日本一本二本三区免费 | 四虎在线永久免费视频网站 | 精品国产91久久久久久久 | 欧美黑人换爱交换乱理伦片 | 国产日韩欧美综合在线 | 免费亚洲一区 | 欧美成人另类人妖 | 肉宠文很肉到处做1v1 | 2022最新a精品视频在线观看 | 互换身体全集免费观看 | 国产巨大bbbb俄罗斯 | a免费看 | 白丝尤物的下面被疯狂蹂躏 | 白丝校花掀起短裙呻吟小说 | 精品国产综合区久久久久久 | 人人揉人人爽五月天视频 | 日韩一区三区 | 日本动漫黄网站在线观看 | 亚洲精美视频 | 天天做天天爱天天操 | crdy在线看亚洲| 手机在线观看精品国产片 | 成人福利在线播放 | 古装床戏做爰无遮挡三级 | 美女大逼逼 | 波多野结衣在线观看视频 |