Java 8 流:替换流集合中的单个项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36704674/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:35:17  来源:igfitidea点击:

Java 8 stream: replace single item in streamed collection

javajava-stream

提问by Patrick

I'm somewhat new to working in Java 8, and am refactoring some older code with (what appears to be a good use case for) a stream operation. The older code "works" but to my eyes it looks really inefficient.

我对使用 Java 8 有点陌生,并且正在使用流操作(这似乎是一个很好的用例)重构一些旧代码。旧代码“有效”,但在我看来,它看起来效率很低。

The short version of my question is that I'm trying to find a single element of a List and replace it with an updated version of that same element (the key is the same, but properties have different values each time the code is called).

我的问题的简短版本是我试图找到 List 的单个元素并将其替换为同一元素的更新版本(键是相同的,但每次调用代码时属性都有不同的值) .

     try
     {
        List<Object> items = lookup(itemCache.getKey());
        for (int i = 0; i < items.size(); i++)
        {
           Object originalObject = items.get(i);
           if (originalObject.getPropValue() == newObject.getPropValue())
           {
              List<Object> newItems = new ArrayList<>(items);
              newItems.set(i, newObject);
              putIntoCache(newObject.getKey(), newItems);
              break;
           }
        }
     } 

     catch (Exception ex) { /*exception handling*/ }

Based on what I've read about streams thus far, it seems that I need to use a .map()or .filter()to isolate the element I want to identify, but that also seems like operations occurring after either filteror mapin the stream statement would be operating on either not the full List or on a List where every item is affected by the .map().

根据我到目前为止所读到的关于流的内容,似乎我需要使用 a.map().filter()来隔离我想要识别的元素,但这也似乎是在流语句之后filtermap在流语句中发生的操作要么不操作完整列表或在每个项目都受.map().

It seems simple, but I am struggling to wrap my head around it. Because the initial lookup is a Listitself, I was thinking the stream could replace all of this. The ArrayList<>()appears in the original code, but ordering of the items isn't important so long as I am able to replace that item by its key.

这看起来很简单,但我正在努力解决它。因为最初的查找是一个List本身,我认为流可以取代所有这些。该ArrayList<>()原代码出现,但项目的顺序并不重要,只要我能够通过它的键替换项目。

If you choose to help, thank you.

如果你选择帮助,谢谢。

采纳答案by Jean Logeart

You can simply do:

你可以简单地做:

List<Object> newItems = items.stream()
    .map(o -> o.getPropValue() == newObject.getPropValue() ? newObject : o)
    .collect(toList());
putIntoCache(newObject.getKey(), newItems);

回答by Adam Kotwasinski

The function you want to apply is "replace the firstelement that matches the prop value". The firstpart (and break statement) are non-trivial (as you depend on all entries processed before that). In other words, it implies that your function depends on some additional state, so the domain can be expressed as boolean * String, where boolean tells you whether the replacement had been done. You can see it starts to get ugly.

您要应用的功能是“替换与 prop 值匹配的第一个元素”。在第一部分(和break语句)是不平凡的(如你依赖于之前处理的所有条目)。换句话说,它意味着你的函数依赖于一些额外的状态,所以域可以表示为boolean * String,其中 boolean 告诉你替换是否已经完成。你可以看到它开始变得丑陋。

If you are okay with replacing allmatching values, then Jean Logeart's answer seems okay.

如果您可以替换所有匹配的值,那么 Jean Logeart 的答案似乎没问题。

回答by Radiodef

Streams are actually not particularly good for this snippet of code because it has an early breakand simultaneously works with both indexes and elements.

Streams 对于这段代码实际上并不是特别好,因为它具有早期break且同时适用于索引和元素的功能。

You can build an equivalent statement like this:

您可以构建这样的等效语句:

List<Object> items = lookup(itemCache.getKey());
IntStream.range(0, items.size())
    .filter(i -> items.get(i).getPropValue() == newItem.getPropValue())
    .findFirst()
    .ifPresent(i -> {
        List<Object> newItems = new ArrayList<>(items);
        newItems.set(i, newObject);
        putIntoCache(newObject.getKey(), newItems);
    });

Is that really better? In my opinion, not particularly. We aren't really using any of the stream features, just replacing control flow syntax with API.

这样真的更好吗?在我看来,不是特别。我们并没有真正使用任何流功能,只是用 API 替换了控制流语法。

If the exact behavior is less important, then there are possibly better examples, like Jean's answer.

如果确切的行为不那么重要,那么可能有更好的例子,比如 Jean 的回答。