簡體   English   中英

有什么方法可以讓這個 stream 更高效?

[英]Any way to make this stream more efficient?

如果不向新的 ArrayList 增加價值,而只是更新原始列表,如何優化這一點?

 String filterval = filter.toLowerCase();
 ArrayList<String> filtredArr = new ArrayList<String>();

                        listArray.forEach(
                                valueText -> {
                                        String val = valueText.toLowerCase();
                                    if (val.startsWith(filterval) || val.contains(filterval))
                                        filtredArr.add(valueText);
                                    else {
                                        Arrays.stream(valueText.split(" ")).forEach(
                                                singleWord -> {
                                                    String word = singleWord.toLowerCase();
                                                    if(word.startsWith(filterval) || word.contains(filterval))
                                                        filtredArr.add(valueText);
                                                }
                                        );
                                    }
                                });

使用流時,最好不要修改 stream 的源,而后者會迭代前者。 (例如看這個。)

關於可讀性和慣用 stream 操作,您的代碼與普通的舊 for 循環幾乎沒有區別(如果您只使用流來執行forEach ,我建議您將其更改為,但您可以修改它以使用更短且更“原子”的 stream 操作鏈,如下例所示。

  • 要獲取至少一個單詞包含filterval的字符串列表:

     List<String> filtered = listArray.stream().filter(str -> str.toLowerCase().contains(filterval)).collect(Collectors.toList());
  • 要獲取至少一個單詞filterval開頭的字符串列表:

     List<String> filtered = listArray.stream().filter(str -> Arrays.stream(str.split(" ")).map(String::toLowerCase).anyMatch(word -> word.startsWith(filterval))).collect(Collectors.toList());
  • 要獲取包含過濾器值的單詞列表(在任何字符串中):

     List<String> filteredWords = listArray.stream().map(String::toLowerCase).flatMap(str -> Arrays.stream(str.split(" "))).filter(word -> word.contains(filterval)).collect(Collectors.toList());

(我假設您未在代碼片段中顯示的listArrayList<String> 。)

筆記

  • 條件val.startsWith(filterval) || val.contains(filterval) val.startsWith(filterval) || val.contains(filterval)完全等同於val.contains(filterval) 原因是,如果一個字符串以filterval ,它也一定意味着它包含它; 一個暗示另一個。
  • 無需計算單個單詞的小寫版本,因為您已經將整個字符串小寫(因此其中的任何單詞也將是小寫的)。
  • 除了單獨處理單個單詞和空格分隔的字符串,我們可以將split應用於所有它們,然后使用filterMap將單詞序列“連接”起來。

最小的、完整的、可驗證的例子

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


public class Main {
    public static void main(String[] args) {
        String filterval = "ba";
        List<String> listArray = List.of("foo", "BAR", "spam EGGS ham bAt", "xxbazz");


        List<String> filtered1 = listArray.stream()
                                          .filter(str -> str.toLowerCase().contains(filterval))
                                          .collect(Collectors.toList());

        List<String> filtered2 =
                listArray.stream()
                         .filter(str -> Arrays.stream(str.split(" "))
                                              .map(String::toLowerCase)
                                              .anyMatch(word -> word.startsWith(filterval)))
                         .collect(Collectors.toList());

        List<String> filtered3 = listArray.stream()
                                          .map(String::toLowerCase)
                                          .flatMap(str -> Arrays.stream(str.split(" ")))
                                          .filter(word -> word.contains(filterval))
                                          .collect(Collectors.toList());

        System.out.println(Arrays.toString(filtered1.toArray()));
        System.out.println(Arrays.toString(filtered2.toArray()));
        System.out.println(Arrays.toString(filtered3.toArray()));
    }
}

Output:

[BAR, spam EGGS ham bAt, xxbazz]
[BAR, spam EGGS ham bAt]
[bar, bat, xxbazz]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM