91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

推薦使用For-Each而不是For循環遍歷元素的原因分析

發布時間:2021-09-06 15:09:37 來源:億速云 閱讀:134 作者:小新 欄目:web開發

這篇文章主要介紹了推薦使用For-Each而不是For循環遍歷元素的原因分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

一、for循環的缺點

在以往遍歷元素的時候,我們通常采用以下的形式:

public class Main {  public static void main(String[] args) {   //1、數組元素   int[] num = new int[] {1,2,3,4,5};   //數組的遍歷   for(int i=0;i<num.length;i++)     System.out.println(num[i]);   //2、對象元素   ArrayList<Person> lists = new ArrayList<>();   lists.add(new Person("張三"));   lists.add(new Person("李四"));   lists.add(new Person("愚公要移山"));   //對象元素的遍歷   for(Iterator<Person> it=lists.iterator();it.hasNext();) {    Person p = it.next();    System.out.println(p.getName());   }  } }

這種寫法看起來還不錯,但是卻并不完美。我們來分析一下,有什么缺點。然后給出解決方案。

問題1:迭代器或索引多次出現,容易造成使用錯誤

從上面兩種遍歷的代碼上來看,對于數組元素是通過索引i來遍歷的,但是整個for循環出現了四次i,對于對象元素是通過迭代器it來遍歷的,但是整個for循環出現了三次it。在for循環遍歷元素的時候,就有多次機會使用了錯誤的變量。而且有時候這些錯誤編譯器無法發現。對整個應用系統造成無法預知的錯誤。

問題2:遍歷對象元素時,需要注意容器類型

比如我們這里使用的是list,當然還有可能是其他容器類型,這些類型在更改時比較麻煩。

問題3:嵌套迭代拋出異常

這種情況比較復雜一些,先來搞個例子。比如說,我們想要列舉每種花,這些花有兩種屬性一種是顏色,一種是大小。

public class Main {  //枚舉顏色和尺寸  enum Color { RED, GREEN, BLUE, BLACK }  enum Size { ONE, TWO, THREE, FOUR, FIVE,     SIX, SEVEN, EIGHT,NINE, TEN}  //定義花  static class Flower{   public Flower(Color color, Size size) {}  }  public static void main(String[] args) {   Collection<Color> colors = Arrays.asList(Color.values());   Collection<Size> sizes = Arrays.asList(Size.values());   List<Flower> flowers = new ArrayList<>();   //for循環添加所有的花和尺寸   for (Iterator<Color> color = colors.iterator(); color.hasNext(); ) {    for (Iterator<Size> size = sizes.iterator(); size.hasNext(); ) {     flowers.add(new Flower(color.next(), size.next()));    }    }   } }

看似人畜無害,現在我們運行一波。

Exception in thread "main" java.util.NoSuchElementException  at java.util.AbstractList$Itr.next(Unknown Source)  at com.f2.Main.main(Main.java:25)

是不是感覺有點奇怪,好像雙重循環遍歷沒啥問題,但是出現了異常,原因是外部的Color迭代器調用了多次,第一層for循環被調用了,但是又在第二層for循環內部被調用了,所以color的next被調用完了。所以出現了NoSuchElementException。但是有時候也不會出現這種情況,場景是外部循環迭代器調用的次數剛好是內部調用的n倍。

問題4:嵌套迭代不拋異常,但是結果不正確

這種情況是外部循環迭代器調用的次數剛好是內部調用的n倍。我們再來個例子:

public class Main {  //枚舉顏色  enum Color { RED, GREEN, BLUE, BLACK }   public static void main(String[] args) {   Collection<Color> colors = Arrays.asList(Color.values());   //兩層for循環   for (Iterator<Color> c1 = colors.iterator(); c1.hasNext(); ) {    for (Iterator<Color> c2 = colors.iterator(); c2.hasNext(); ) {     System.out.println(c1.next()+" "+c2.next());    }    }   } }

現在對顏色進行for循環遍歷,一共兩層for循環,因為一共有四種顏色,兩層for循環應該是打印16個結果。現在運行一遍看看結果:

RED RED GREEN GREEN BLUE BLUE BLACK BLACK

沒錯,確實是打印了四條。原因和問題三是一樣的。有一種方式可以很好地解決這種嵌套的問題。

嵌套迭代問題解決:

直接看代碼。既然是外部的迭代器it在內部使用了,那我在內部和外部之間用一個變量緩存起來不就好了。

public class Main {  //枚舉顏色  enum Color { RED, GREEN, BLUE, BLACK }  public static void main(String[] args) {   Collection<Color> colors = Arrays.asList(Color.values());   //for循環   for (Iterator<Color> c1 = colors.iterator(); c1.hasNext(); ) {    //用一個變量緩存起來    Color c = c1.next();    for (Iterator<Color> c2 = colors.iterator(); c2.hasNext(); ) {     System.out.println(c+" "+c2.next());    }    }   } }

現在再來運行,就可以很好地得出16種結果了。這種方式也比較不錯,但是卻不能很好地解決問題1和問題2。因此,為了解決這一現象,大佬Joshua  Bloch在書中提出,推薦使用for-each循環來代替for循環。

二、for-each循環

既然作者推薦使用for-each循環,我們看看他有什么好處。是如何解決上面的問題的。

public class Main {  //枚舉顏色和尺寸  enum Color { RED, GREEN, BLUE, BLACK }  enum Size { ONE, TWO, THREE, FOUR, FIVE,     SIX, SEVEN, EIGHT,NINE, TEN}  //定義花  static class Flower{   public Flower(Color color, Size size) {}  }  public static void main(String[] args) {   Collection<Color> colors = Arrays.asList(Color.values());   Collection<Size> sizes = Arrays.asList(Size.values());   List<Flower> flowers = new ArrayList<>();   //for-each循環   for (Color color:colors) {    for (Size size:sizes ) {     flowers.add(new Flower(color, size));    }    }   } }

看里面的for-each循環。上面的問題就全都解決了。好吧,可能你會感覺,就這?還有一個好處還沒說,再往下看。

for-each 循環不僅允許遍歷集合和數組,還允許遍歷實現 Iterable 接口的任何對象,該接口由單個方法組成。接 口定義如下:

public interface Iterable<E> {  // Returns an iterator over the elements in this iterable  Iterator<E> iterator(); }

如果必須從頭開始編寫自己的 Iterator 實現,那么實現 Iterable 會有點棘手,但是如果你正在編寫表示一組元素  的類型,那么你應該強烈考慮讓它實現 Iterable 接口,甚至可以選擇不讓它實現 Collection 接口。這允許用戶使用for-each  循環遍歷類型,他們會永遠感激不盡的 。

但是,有三種常見的情況是你不能分別使用 for-each 循環的:

(1)有損過濾(Destructive filtering):如果需要遍歷集合,并刪除指定選元素,則需要使用顯式迭代器,以便可以調用其 remove  方法。通常可以使用在 Java 8 中添加的 Collection 類中的 removeIf 方法,來避免顯式遍歷。

(2)轉換:如果需要遍歷一個列表或數組并替換其元素的部分或全部值,那么需要列表迭代器或數組索引來替換元素的值。

(3)并行迭代:如果需要并行地遍歷多個集合,那么需要顯式地控制迭代器或索引變量,以便所有迭代器或索引變量都可以同步進行 。

如果發現自己處于這些情況中的任何一種,請使用傳統的 for 循環,并警惕本條目中提到的陷阱 。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“推薦使用For-Each而不是For循環遍歷元素的原因分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

周口市| 吉木乃县| 谷城县| 睢宁县| 噶尔县| 左权县| 辽阳县| 岳阳县| 隆回县| 碌曲县| 安义县| 棋牌| 乐清市| 曲阳县| 江川县| 卓尼县| 枣庄市| 衡阳县| 长葛市| 金沙县| 河北省| 五莲县| 丘北县| 福清市| 寿宁县| 文水县| 黄大仙区| 南京市| 治多县| 西城区| 永清县| 山东省| 林周县| 响水县| 昌都县| 扶绥县| 横山县| 云安县| 金溪县| 射阳县| 察隅县|