简体   繁体   English

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

[英]Java 8 stream: replace single item in streamed collection

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. 我在使用Java 8时有些新手,并且正在重构一些旧的代码(对于流操作来说似乎是一个很好的用例)。 The older code "works" but to my eyes it looks really inefficient. 较旧的代码“有效”,但在我看来它看起来效率很低。

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 filter or map in the stream statement would be operating on either not the full List or on a List where every item is affected by the .map() . 基于我到目前为止所读到的关于流的内容,似乎我需要使用.map().filter()来隔离我想要识别的元素,但这看起来像是在filtermap之后发生的操作在stream语句中,不是在完整列表上运行,也不在列表中运行,其中每个项都受.map()

It seems simple, but I am struggling to wrap my head around it. 这似乎很简单,但我正在努力绕过它。 Because the initial lookup is a List itself, I was thinking the stream could replace all of this. 因为初始查找是List本身,所以我认为流可以替换所有这些。 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. ArrayList<>()出现在原始代码中,但只要我能够用其键替换该项,那么项的排序就不重要了。

If you choose to help, thank you. 如果您选择帮助,谢谢。

You can simply do: 你可以简单地做:

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

The function you want to apply is "replace the first element that matches the prop value". 您要应用的函数是“替换与prop值匹配的第一个元素”。 The first part (and break statement) are non-trivial (as you depend on all entries processed before that). 第一部分(和break语句)是非平凡的(因为您依赖于之前处理的所有条目)。 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. 换句话说,它意味着你的函数依赖于一些额外的状态,所以域可以表示为boolean * String ,其中boolean告诉你是否已经完成了替换。 You can see it starts to get ugly. 你可以看到它开始变得难看。

If you are okay with replacing all matching values, then Jean Logeart's answer seems okay. 如果您可以替换所有匹配值,那么Jean Logeart的答案似乎没问题。

Streams are actually not particularly good for this snippet of code because it has an early break and 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的回答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM