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

新手上路,请多包涵

我对使用 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<>() 出现在原始代码中,但只要我能够用它的键替换该项目,项目的顺序并不重要。

如果您选择帮助,谢谢。

原文由 Patrick 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 443
2 个回答

你可以简单地做:

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

原文由 Jean Logeart 发布,翻译遵循 CC BY-SA 3.0 许可协议

流对于这段代码实际上不是特别好,因为它有一个早期的 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 的回答。

原文由 Radiodef 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题