成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么推薦使用For-Each而不是For循環(huán)遍歷元素?

開發(fā) 前端
for循環(huán)是平時寫代碼用的最多的,但是之前看《Effective java》,大佬在某些場景寫并不推薦。結(jié)合著自己之前刷算法題的經(jīng)歷,受益匪淺。

 [[383743]]

for循環(huán)是平時寫代碼用的最多的,但是之前看《Effective java》,大佬在某些場景寫并不推薦。結(jié)合著自己之前刷算法題的經(jīng)歷,受益匪淺。

一、for循環(huán)的缺點

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

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

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

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

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

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

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

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

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

  1. public class Main { 
  2.  //枚舉顏色和尺寸 
  3.  enum Color { RED, GREEN, BLUE, BLACK } 
  4.  enum Size { ONE, TWO, THREE, FOUR, FIVE, 
  5.     SIX, SEVEN, EIGHT,NINE, TEN} 
  6.  //定義花 
  7.  static class Flower{ 
  8.   public Flower(Color color, Size size) {} 
  9.  } 
  10.  public static void main(String[] args) { 
  11.   Collection<Color> colors = Arrays.asList(Color.values()); 
  12.   Collection<Size> sizes = Arrays.asList(Size.values()); 
  13.   List<Flower> flowers = new ArrayList<>(); 
  14.   //for循環(huán)添加所有的花和尺寸 
  15.   for (Iterator<Color> color = colors.iterator(); color.hasNext(); ) { 
  16.    for (Iterator<Sizesize = sizes.iterator(); size.hasNext(); ) { 
  17.     flowers.add(new Flower(color.next(), size.next())); 
  18.    }  
  19.   }  
  20.  } 

看似人畜無害,現(xiàn)在我們運行一波。

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

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

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

這種情況是外部循環(huán)迭代器調(diào)用的次數(shù)剛好是內(nèi)部調(diào)用的n倍。我們再來個例子:

  1. public class Main { 
  2.  //枚舉顏色 
  3.  enum Color { RED, GREEN, BLUE, BLACK }  
  4.  public static void main(String[] args) { 
  5.   Collection<Color> colors = Arrays.asList(Color.values()); 
  6.   //兩層for循環(huán) 
  7.   for (Iterator<Color> c1 = colors.iterator(); c1.hasNext(); ) { 
  8.    for (Iterator<Color> c2 = colors.iterator(); c2.hasNext(); ) { 
  9.     System.out.println(c1.next()+" "+c2.next()); 
  10.    }  
  11.   }  
  12.  } 

現(xiàn)在對顏色進(jìn)行for循環(huán)遍歷,一共兩層for循環(huán),因為一共有四種顏色,兩層for循環(huán)應(yīng)該是打印16個結(jié)果。現(xiàn)在運行一遍看看結(jié)果:

  1. RED RED 
  2. GREEN GREEN 
  3. BLUE BLUE 
  4. BLACK BLACK 

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

嵌套迭代問題解決:

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

  1. public class Main { 
  2.  //枚舉顏色 
  3.  enum Color { RED, GREEN, BLUE, BLACK } 
  4.  public static void main(String[] args) { 
  5.   Collection<Color> colors = Arrays.asList(Color.values()); 
  6.   //for循環(huán) 
  7.   for (Iterator<Color> c1 = colors.iterator(); c1.hasNext(); ) { 
  8.    //用一個變量緩存起來 
  9.    Color c = c1.next(); 
  10.    for (Iterator<Color> c2 = colors.iterator(); c2.hasNext(); ) { 
  11.     System.out.println(c+" "+c2.next()); 
  12.    }  
  13.   }  
  14.  } 

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

二、for-each循環(huán)

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

  1. public class Main { 
  2.  //枚舉顏色和尺寸 
  3.  enum Color { RED, GREEN, BLUE, BLACK } 
  4.  enum Size { ONE, TWO, THREE, FOUR, FIVE, 
  5.     SIX, SEVEN, EIGHT,NINE, TEN} 
  6.  //定義花 
  7.  static class Flower{ 
  8.   public Flower(Color color, Size size) {} 
  9.  } 
  10.  public static void main(String[] args) { 
  11.   Collection<Color> colors = Arrays.asList(Color.values()); 
  12.   Collection<Size> sizes = Arrays.asList(Size.values()); 
  13.   List<Flower> flowers = new ArrayList<>(); 
  14.   //for-each循環(huán) 
  15.   for (Color color:colors) { 
  16.    for (Size size:sizes ) { 
  17.     flowers.add(new Flower(color, size)); 
  18.    }  
  19.   }  
  20.  } 

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

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

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

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

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

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

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

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

如果發(fā)現(xiàn)自己處于這些情況中的任何一種,請使用傳統(tǒng)的 for 循環(huán),并警惕本條目中提到的陷阱 。

本文轉(zhuǎn)載自微信公眾號「愚公要移山」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系愚公要移山公眾號。

 

責(zé)任編輯:武曉燕 來源: 愚公要移山
相關(guān)推薦

2013-03-25 10:14:18

NginxApache

2020-09-15 09:23:19

C++WindowsC#

2025-05-16 02:00:00

HashMapJava代碼

2021-03-26 11:50:28

Linuxexals

2023-03-01 10:42:58

gRPC服務(wù)端設(shè)置

2021-06-30 12:47:12

標(biāo)簽HTML分辨率

2019-04-19 11:56:48

框架AI開發(fā)

2023-02-26 11:15:42

緩存循環(huán)依賴

2021-08-14 09:04:58

TypeScriptJavaScript開發(fā)

2021-10-30 19:57:00

HTTP2 HTTP

2012-10-10 16:52:21

CentOSDebianUbuntu

2017-09-11 19:58:06

PostgreSQLMySQL數(shù)據(jù)庫

2020-06-02 14:17:55

QWER排列鍵盤打印機(jī)

2023-11-02 08:20:54

SocketZygoteAndroid

2020-07-24 09:20:44

MapObject前端

2025-03-04 00:25:55

Go開發(fā)者切片

2024-06-24 00:00:00

AVIFJPEG圖像格式

2023-09-29 11:50:10

接口編程代碼

2016-10-11 11:13:15

Linus Torva

2019-09-24 09:33:53

MySQLB+樹InnoDB
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产日韩欧美精品一区二区三区 | 国产成人一区二 | 91国产视频在线观看 | 日本天堂一区二区 | 日韩av在线中文字幕 | 91麻豆精品国产91久久久久久 | 欧美日韩视频在线第一区 | 一区视频在线免费观看 | 久久99深爱久久99精品 | 国产精品亚洲第一区在线暖暖韩国 | 成年免费在线观看 | 日韩在线小视频 | 日日人人 | 成人免费视频观看视频 | 黄色一级大片在线免费看产 | 91视频官网 | 欧美一区二区三区在线 | 成人影院网站ww555久久精品 | 国产精品一二三区 | 黄色免费三级 | 国产精品区二区三区日本 | 国产精品国产精品国产专区不卡 | 国产一区二区三区四区区 | 午夜免费福利电影 | 91玖玖| www.日韩系列 | 国产一区91精品张津瑜 | 天天噜天天干 | 亚洲成人第一页 | av网站观看 | 国产一区二区在线91 | 婷婷福利 | 免费看国产片在线观看 | 国产成人午夜高潮毛片 | 国产高清精品在线 | 在线国产小视频 | 中文字幕三区 | 亚洲风情在线观看 | 男人天堂999| 成人小视频在线观看 | 亚洲综合视频 |