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

时间:2016-04-18 21:32:21

标签: java java-stream

我在使用Java 8时有点新手,并且正在重构一些旧的代码(对于一个很好的用例来说)是一个流操作。较旧的代码“有效”但在我看来它看起来效率很低。

我的问题的简短版本是我正在尝试查找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*/ }

基于我到目前为止所读到的关于流的内容,似乎我需要使用.map().filter()来隔离我想要识别的元素,但这似乎也就像发生的操作一样在流语句中的filtermap之后,不是在完整列表上运行,也不在列表中运行,其中每个项目都受.map()的影响。

这似乎很简单,但我正在努力绕过它。因为初始查找本身是List,所以我认为流可以替换所有这些。 ArrayList<>()出现在原始代码中,但只要我能够通过其密钥替换该项目,项目的排序就不重要了。

如果您选择帮助,谢谢。

3 个答案:

答案 0 :(得分:21)

您可以这样做:

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

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

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

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);
    });

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

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