繁体   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