如何根据 HashMap 中的值修改 Stream 的元素

How to modify an element of the Stream based on the value in a HashMap

如果可以在我的 HashMap.

中找到相应的 key/value 对,我想覆盖我的对象 status

示例模型:

public class Url {
  private String url;
  private String status;
}
private List<Url> overwriteStatus(List<Url> myObjects) {
   final var myChecklist = Map.of("www.foo.com", "blocked");

  //if the key exists in `myChecklist`, then overwrite the status
  myObjects.stream().forEach(item -> Optional.ofNullable(myChecklist.get(item.getUrl())).ifPresent(item::setStatus));

  return myObjects;
}

我目前使用 Optional 的方法感觉很乱。

检查值是否存在于 HashMap 中的最佳方法是什么?如果存在,请在下一步中使用该值?

我认为您不应该使用 Stream,因为您在迭代集合时正在修改对象。

只需使用一个循环

for (Url item : myObjects) {
  String status = myCheckList.get(item.getUrl());
  if (status == null) continue;
  u.setStatus(status);
}

Documentation 用于 流 API 警告不要 使用 有状态流.

流中使用的函数必须,即不会导致流元素发生突变,不会修改对象流外(这基本上就是您的代码中发生的情况)。

您的任务可以在不违反上述准则的情况下通过流来完成。为此,如果必须应用新的 status,则无需更改状态,而是需要创建 new 对象。

我还建议 Url 对象不可变。这样可以在应用程序的不同部分安全地重用相同的实例。

private List<Url> overwriteStatus(List<Url> myObjects, 
                                  Map<String, String> myChecklist) {

    return myObjects.stream()
            .map(item -> !myChecklist.containsKey(item.getUrl()) ? item :
                    new Url(item.getUrl(), myChecklist.get(item.getUrl())))
            .collect(Collectors.toList());
}

ImmutableclassUrl(没有setter,所有字段都是final

public class Url {
    private final String url;
    private final String status;

    // constructor and getters
}

注:

  • 关于 Optional 类型,在 JDK 中引入它仅用于一个特定目的:表示 return可能产生 null 的方法类型,仅此而已。仅按照链接方法的顺序使用 Optional 的做法被认为是 反模式