【问题标题】:Modify a map using stream使用流修改地图
【发布时间】:2019-08-21 20:49:57
【问题描述】:

我有一张地图,我正在遍历它并使用for 循环修改地图的值。我想知道是否有一种方法可以使用 Java 8 流。

这是我的代码:

Map<String,MyObject> myMap = getResultMap();
for (Map.Entry<String, MyObject> entry : myMap.entrySet()) {
    entry.getValue.setName(getName());
    entry.getValue.setId(getId());
    entry.getValue.setDept(getDept());
    entry.getValue.isValid(isValid();
    entry.getValue.setPipeLine(getPipeLine());
}

基本上,我想流式传输地图值并设置值并将其作为新地图获取。

【问题讨论】:

  • “使用流修改地图” - 不要这样做/尝试这样做。您不能修改流。流被设计成功能性的:如果你使用过它们,它们就消失了。此外,side-effects in streams are discouraged (See paragraph "side-effects"),因此您不应该尝试修改流的底层数据结构。
  • 您可以根据流的结果创建具有更新条目的新地图。但我不确定它是否会比 for-loop 更具可读性。
  • 从技术上讲,您可以这样做,但不应更改您正在流式传输的集合,因为这可能会导致意外行为。您可以使用 stream().map().collect() 构建新地图。
  • 问题含糊不清。您显示的代码不会创建新地图;它修改了旧地图的值。是否要更改 MyObject 实例?您想修改映射以使新对象与其键相关联吗?您想要一个旧值已修改的新地图吗?还是具有新价值观的新地图?

标签: java lambda java-8 java-stream


【解决方案1】:

您可以通过流操作获得一个新的Stream 或一个新的Map,但Stream 不能改变数据(但您可以创建一个 lambda 来做任何您想做的事情)。例如,使用您的代码示例:

Map<String, MyObject> myMap = getResultMap();
Map<String, MyObject> newMap = myMap.entrySet().stream()
            .collect(Collectors.toMap(Map.Entry::getKey, entry ->
            {
                entry.getValue().setName(getName());
                entry.getValue().setId(getId());
                entry.getValue().setDept(getDept());
                entry.getValue().setValid(isValid());
                entry.getValue().setPipeLine(getPipeLine());
                return entry.getValue();
            }
            ));

但不要更新Stream 中的共享可变变量!它会产生很多问题。

最好创建MyObject类的新实例而不是修改myMap:

Map<String, MyObject> newMap = myMap.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry ->
                        {
                            MyObject myObject = new MyObject();
                            myObject.setName(getName());
                            myObject.setId(getId());
                            myObject.setDept(getDept());
                            myObject.setValid(isValid();
                            myObject.setPipeLine(getPipeLine());
                            return myObject;
                        }
                ));

【讨论】:

  • 你能提供代码示例和我的代码吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
相关资源
最近更新 更多