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

For循環和While循環之流的終結

開發 前端
循環語句是編程的基本組成部分。列表中的每一項都有用處,讀取輸入,直到輸入結束,在屏幕上放置n個輸入框。每當看到PR中的代碼添加了循環語句,我都怒不可遏。現在我必定仔細檢查代碼,確保循環可以終止。

 本文轉載自公眾號“讀芯術”(ID:AI_Discovery)

循環語句是編程的基本組成部分。列表中的每一項都有用處,讀取輸入,直到輸入結束,在屏幕上放置n個輸入框。每當看到PR中的代碼添加了循環語句,我都怒不可遏。現在我必定仔細檢查代碼,確保循環可以終止。

[[389350]]

我希望所有運行良好的語句庫中都看不到循環語句的蹤影,但仍然有一些悄悄混進來,所以我想告訴大家如何消除循環語句。

讓循環語句終結的關鍵是函數式編程。只需提供要在循環中執行的代碼以及循環的參數(需要循環的內容)即可。我用Java作示范語言,但其實許多語言都支持這種類型的函數式編程,這種編程可以消除代碼中的循環。

最簡單的情況是對列表中的每個元素執行操作。

  1. List<Integer> list = List.of(1, 2, 3); 
  2. // bare for loop.  
  3. for(int i : list) { 
  4.    System.out.println("int = "+ i); 
  5. }// controlled for each 
  6. list.forEach(i -> System.out.println("int = " + i)); 

在這種最簡單的情況下,無論哪種方法都沒有太大優勢。但第二種方法可以不使用bare for循環,而且語法更簡潔。

我覺得forEach語句也有問題,應該只應用于副作用安全的方法。我所說的安全副作用是指不改變程序狀態。上例只是記錄日志,因此使用無礙。其他有關安全副作用的示例是寫入文件、數據庫或消息隊列。

不安全的副作用會更改程序狀態。下面為示例及其解決方法:

  1. // bad side-effect, the loop alters sum 
  2. int sum = 0; 
  3. for(int i : list) { 
  4.     sum += i; 
  5. System.out.println("sum = " + sum);// no side-effect, sum iscalculated by loop 
  6. sum = list 
  7.        .stream() 
  8.        .mapToInt(i -> i) 
  9.        .sum(); 
  10. System.out.println("sum = " + sum); 

另一個常見的例子:

  1. // bad side-effect, the loop alters list2 
  2. List<Integer> list2 = new ArrayList<>(); 
  3. for(int i : list) { 
  4.    list2.add(i); 
  5. list2.forEach(i -> System.out.println("int = " + i));// no sideeffect, the second list is built by the loop 
  6. list2 = list 
  7.          .stream() 
  8.          .collect(Collectors.toList()); 
  9. list2.forEach(i -> System.out.println("int = " + i)); 

當你需要處理列表項方法中的索引時就會出現問題,但可以解決,如下:

  1. // bare for loop with index
  2. for(int i = 0; i < list.size(); i++) { 
  3.     System.out.println("item atindex "  
  4.       + i  
  5.       + " = "  
  6.       + list.get(i)); 
  7. }// controlled loop with index
  8. IntStream.range(0, list.size()) 
  9.    .forEach(i ->System.out.println("item at index " 
  10.     + i 
  11.     + " = " 
  12.     + list.get(i))); 

老生常談的問題:讀取文件中的每一行直到文件讀取完畢如何解決?

  1. BufferedReader reader = new BufferedReader( 
  2.        new InputStreamReader( 
  3.       LoopElimination.class.getResourceAsStream("/testfile.txt"))); 
  4. // while loop with clumsy looking syntax 
  5. String line; 
  6. while((line = reader.readLine()) != null) { 
  7.    System.out.println(line); 
  8. }reader = new BufferedReader( 
  9.        new InputStreamReader( 
  10.       LoopElimination.class.getResourceAsStream("/testfile.txt"))); 
  11. // less clumsy syntax 
  12. reader.lines() 
  13.    .forEach(l ->System.out.println(l)); 

應對上述情況有一個非常簡便的lines方法,可以返回Stream類型。但是如果一個字符一個字符地讀取呢?InputStream類沒有返回Stream的方法。我們必須創建自己的Stream:

  1. InputStream is = 
  2.    LoopElimination.class.getResourceAsStream("/testfile.txt"); 
  3. // while loop with clumsy looking syntax 
  4. int c; 
  5. while((c = is.read()) != -1) { 
  6.   System.out.print((char)c); 
  7. // But this is even uglier 
  8. InputStream nis = 
  9.    LoopElimination.class.getResourceAsStream("/testfile.txt"); 
  10. // Exception handling makes functional programming ugly 
  11. Stream.generate(() -> { 
  12.    try { 
  13.       return nis.read(); 
  14.    } catch (IOException ex) { 
  15.       throw new RuntimeException("Errorreading from file", ex); 
  16.    } 
  17. }) 
  18.  .takeWhile(ch -> ch != -1) 
  19.  .forEach(ch ->System.out.print((char)(int)ch)); 

這種情況下while循環看起來更好。此外,Stream版本還使用了可以返回無限項目流的 generate函數,因此必須進一步檢查以確保生成過程終止,這是由于takeWhile方法的存在。

InputStream類存在問題,因為缺少peek 方法來創建可輕松轉換為Stream的Iterator。它還會拋出一個檢查過的異常,這樣函數式編程就會雜亂無章。在這種情況下可以使用while語句讓PR通過。

為了使上述問題更簡潔,可以創建一個新的IterableInputStream類型,如下:

  1. static class InputStreamIterable implements Iterable<Character> { 
  2.   private final InputStream is
  3.   public InputStreamIterable(InputStreamis) { 
  4.     this.is = is
  5.   } 
  6.   public Iterator<Character>iterator() { 
  7.      return newIterator<Character>() {               
  8.         public boolean hasNext() { 
  9.            try { 
  10.              // poor man's peek: 
  11.              is.mark(1); 
  12.              boolean ret = is.read() !=-1; 
  13.              is.reset(); 
  14.              return ret; 
  15.            } catch (IOException ex) { 
  16.              throw new RuntimeException( 
  17.                     "Error readinginput stream", ex); 
  18.            } 
  19.         } 
  20.         public Character next() { 
  21.            try { 
  22.              return (char)is.read(); 
  23.            } catch (IOException ex) { 
  24.              throw new RuntimeException( 
  25.                    "Error readinginput stream", ex); 
  26.            } 
  27.         } 
  28.      }; 
  29.   } 

這樣就大大簡化了循環問題:

  1. // use a predefined inputstream iterator: 
  2. InputStreamIterable it = new InputStreamIterable( 
  3.     LoopElimination.class.getResourceAsStream("/testfile.txt")); 
  4. StreamSupport.stream(it.spliterator(), false
  5.    .forEach(ch -> System.out.print(ch)); 

如果你經常遇到此類while循環,那么你可以創建并使用一個專門的Iterable類。但如果只用一次,就不必大費周章,這只是新舊Java不兼容的一個例子。

所以,下次你在代碼中寫for 語句或 while語句的時候,可以停下來思考一下如何用forEach 或 Stream更好地完成你的代碼。

 

責任編輯:華軒 來源: 讀芯術
相關推薦

2021-12-09 23:20:31

Python循環語句

2021-06-07 06:10:22

C++While循環For 循環

2024-02-26 12:13:32

C++開發編程

2009-07-21 14:03:00

Scalaif表達式while循環

2010-09-08 17:00:22

SQLWHILE循環

2023-02-25 16:33:12

Luawhile

2023-04-20 13:59:01

Pythonwhile循環的

2023-08-21 12:31:41

BashForWhile

2010-09-09 16:34:19

SQL循環while

2022-09-30 07:32:48

循環while循環體

2020-11-13 07:22:46

Java基礎While

2020-12-11 05:57:01

Python循環語句代碼

2022-01-27 09:35:45

whiledo-while循環Java基礎

2010-01-07 15:42:57

VB.NET WhilEnd While循環

2021-01-28 09:55:50

while(1)for(;;)Linux

2021-03-17 11:16:58

while(1)for(;;)語言

2010-03-19 14:18:07

Java Socket

2024-11-08 16:13:43

Python開發

2009-11-10 11:30:12

VB.NET循環語句

2022-10-28 07:38:06

Javawhile循環
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 六月成人网 | 久久久久久国产精品免费免费 | 国产精品不卡 | 免费观看一级特黄欧美大片 | 亚洲高清免费视频 | 天天操一操| 欧美一区永久视频免费观看 | 免费在线观看成年人视频 | 在线欧美视频 | 国产精品一区在线 | 亚洲精品一区二区网址 | 亚洲国产精久久久久久久 | 日韩中文一区二区三区 | 国产精品久久久亚洲 | 毛片一区二区三区 | 在线播放国产视频 | 久久伊| 一区二区在线看 | 国产一区影院 | 一区二区三区视频 | 精品九九| 午夜视频一区 | 能看的av | 成人精品国产 | 成人免费大片黄在线播放 | 波多野结衣在线观看一区二区三区 | 久久91精品国产一区二区三区 | 一级在线视频 | 狠狠色狠狠色综合系列 | 国产亚洲精品久久久久久豆腐 | 看一级毛片视频 | 国产精品影视在线观看 | 精品一区二区久久久久久久网站 | 日韩视频国产 | 国产成人一区 | 日本不卡一区二区 | 国产97视频在线观看 | 日韩欧美视频免费在线观看 | 毛片黄片免费看 | 国产精品1区2区 | 亚洲444eee在线观看 |