2017-08-22 165 views
4

我已經開始使用Java 8並嘗試將代碼中的一些循環和舊語法轉換爲lambdas和流。將循環(while和for)轉換爲流

因此,例如,我想這一點的同時轉換和循環到流,但我沒有得到它的權利:

List<String> list = new ArrayList<>(); 
if (!oldList.isEmpty()) {// old is a List<String> 
    Iterator<String> itr = oldList.iterator(); 
    while (itr.hasNext()) { 
     String line = (String) itr.next(); 
     for (Map.Entry<String, String> entry : map.entrySet()) { 
      if (line.startsWith(entry.getKey())) { 
     String newline = line.replace(entry.getKey(),entry.getValue()); 
       list.add(newline); 
      } 
     } 
    } 
} 

我想知道是否有可能以上面的例子轉換到for循環中有一個while循環的單個流。

+3

「試圖將我的代碼中的一些循環和舊語法轉換爲lambda和流。」你想在這裏獲得什麼?流可以簡化一些任務,但有時循環更易於閱讀和維護。另外爲什麼你有'迭代器 itr = oldList.iterator(); while(itr.hasNext()){String line =(String)itr.next(); ...}而不是'for(String line:oldList){...}'?你也可以刪除if(!oldList.isEmpty()),因爲如果list是空的,你不會迭代。 – Pshemo

+0

嗨Pshemo,謝謝你這麼快速的迴應。它是一個已經存在的代碼,所以我只是想知道是否可以更新一些到Streams的循環。我已經做了一些沒有錯誤,但只是有好奇心,如果可以做到這一點,如上面的嵌套循環。 –

+2

這本質上是問「如何用流代替嵌套循環」:https://stackoverflow.com/q/27174700/1531971 – jdv

回答

4

如上所述,在這裏使用流並不真正增加價值,因爲它使代碼更難以閱讀/理解。我知道你是在做一個學習練習。話雖這麼說,做這樣的事情,這是一個稍微函數式方法,因爲它沒有從流本身添加到列表中的一個副作用:

list = oldList.stream().flatMap(line-> 
      map.entrySet().stream() 
        .filter(e->line.startsWith(e.getKey())) 
        .map(filteredEntry->line.replace(filteredEntry.getKey(),filteredEntry.getValue())) 
     ).collect(Collectors.toList()); 
3

我不明白你爲什麼想在這裏使用流,但它是可能的。

創建一些測試輸入:

List<String> oldList = Arrays.asList("adda","bddb","cddc"); 
Map<String,String> map = new HashMap<>(); 
map.put("a", "x"); 
map.put("b", "y"); 
map.put("c", "z"); 

List<String> list = new ArrayList<>(); 

的實際代碼:

oldList.stream() 
    .forEach(line -> map.entrySet().stream() 
      .filter(entry -> line.startsWith(entry.getKey())) 
      .forEach(entry -> list.add(line.replace(entry.getKey(),entry.getValue())))); 

打印結果:

list.forEach(System.out::println); 

那就是:

xddx 
yddy 
zddz 
+0

非常感謝你羅賓,它的工作。 –

1

您可以使用嵌套在從oldList列表創建的流中的流來實現它。嵌套流扮演了從oldList映射當前值與map中定義的映射器(例如,

public static void main(String[] args) { 
    final List<String> oldList = Arrays.asList("asd-qwe", "zxc", "123"); 
    final Map<String, String> map = new HashMap<String, String>() {{ 
     put("asd", "zcx"); 
     put("12", "09"); 
     put("qq", "aa"); 
    }}; 

    List<String> result = oldList.stream() 
      .map(line -> map.entrySet() 
        .stream() 
        .filter(entry -> line.startsWith(entry.getKey())) 
        .map(entry -> line.replace(entry.getKey(), entry.getValue())) 
        .collect(Collectors.toList()) 
      ) 
      .flatMap(Collection::stream) 
      .collect(Collectors.toList()); 


    System.out.println(result); 
} 

以下示例生成像輸出:

[zcx-qwe, 093] 

建議的解決方案如果需要,可以很容易地並行化。沒有副作用的功能性方法。

+0

這是不一樣的,原來的問題不使用'findFirst'或'findAny',它會查看地圖中的所有鍵。 –

+0

@M。普羅霍羅夫良好的抓住,謝謝你指出。答案更新以滿足這一期望。 –

3

要回答你的問題,這是一個1-liner:

List<String> list = oldList.stream() 
    .filter(line -> map.keySet().stream().anyMatch(line::startsWith)) 
    .map(line -> map.entrySet().stream() 
     .filter(entry -> line.startsWith(entry.getKey())) 
     .map(entry -> line.replace(entry.getKey(), entry.getValue())) 
     .findFirst().get()) 
    .collect(Collectors.toList()); 
+0

@Pshemo nah - 它需要'.findFirst()。get()'將流轉換爲字符串。這個編譯:) – Bohemian