java - 如何在没有重复操作开销的情况下进行过滤和映射

标签 java performance java-stream

在某些情况下,使用 Java 8 Stream 让我重复执行某些操作,如果没有 Stream 就可以避免,但我认为问题不在于流,而在于我。

一些例子:

private class Item {
    String id;
    List<String> strings;
}

// This method, filters only the Items that have the strToFind, and
// then maps it to a new string, that has the id and the str found
private void doIt(List<Item> items, String strToFind) {
    items.stream().filter(item -> {
        return item.strings.stream().anyMatch(str -> this.operation(str, strToFind));
    }).map(item -> {
        return item.id + "-" + item.strings.stream()
            .filter(str -> this.operation(str, strToFind)).findAny().get();
    });
}

// This operation can have a lot of overhead, therefore
// it would be really bad to apply it twice
private boolean operation(String str, String strToFind) {
    return str.equals(strToFind);
}

如您所见,函数 operation 被每个项目调用两次,我不希望这样。我首先想到的是直接映射并在找不到时返回“null”,然后过滤空值,但如果这样做,我将失去对 Item 的引用,因此无法使用 id。

最佳答案

我想你可能想要这种行为:

items.stream().map(item -> {
        Optional<String> optional = item.strings.stream().filter(string -> operation(string, strToFind)).findAny();
        if(optional.isPresent()){
            return item.id + "-" + optional.get();
        }
        return null;
    }).filter(e -> e != null);

编辑: 因为当你之后做 map 时,你会丢失过滤器中获得的信息,但没有什么能阻止你只在 map 中进行操作,然后再过滤。

编辑 2: 正如@Jorn Vernee 指出的那样,您可以进一步缩短它:

private void doIt(List<Item> items, String strToFind) {
    items.stream().map(item -> item.strings.stream().filter(string -> operation(string, strToFind)).findAny()
            .map(found -> item.id + "-" + found).orElse(null)).filter(e -> e != null);
}

关于java - 如何在没有重复操作开销的情况下进行过滤和映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42422722/

相关文章:

java - Linq C# 中 Java 的 Stream#Peek 方法的等价物是什么?

Java,使用反射进行列表排序

java - 以线程安全的方式使用 ExecutorService 和 ProgressMonitor

c# - Web 服务的快速和肮脏的性能测试 - 我有什么选择?

c# - 晦涩的编译器的 lambda 表达式翻译

c++ - 使用 std::map 从数组中删除重复项

Java 8 Streams如何避免使用map或set进行过滤?

java - 我的 Java 通用控制台输入法有改进吗?

java - 获取 LinkedHashMap 的前一个元素

java - 需要触发JavaFX TableView内置的Table Menu Button