使用 put() 与 putAll() 时导致无限循环的原因

What causes an Infinite loop when using put() vs putAll()

在下面的简单示例代码中,我想快速将 HashMap 'additional' 放入 Process 对象的有效负载中。但是,我注意到当我使用 .put() 以便将数据更深地嵌套在附加键值(“exampleData”)后面时,会发生无限循环:

public class Process {

    public Map<String, Object> getPayload() {
        return payload;
    }

    public void setPayload(Map<String, Object> payload) {
        this.payload = payload;
    }

    Map<String, Object> payload;
}
    public static void main(String[] args) {
        Process process = new Process();
        LinkedHashMap<String, Object> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("uuid", "uuid");
        process.setPayload(linkedHashMap);
        Map<String, Object> additional = new HashMap<>();
        additional.putAll(process.getPayload()); //additional.put("exampleData", process.getPayload());
        process.getPayload().put("additionalData",additional);
    }

当使用 putAll() 执行代码时,不会发生无限循环,Process 对象如下所示:

但是,当使用 put() 而不是 putAll() 时,会发生无限循环,有效负载包含自身并发生 WhosebugError:

是什么导致了这个无限循环?为什么 putAll() 不受此影响?

行后:

additional.put("exampleData", process.getPayload());

additional 现在有对进程负载的引用。相关对象图如下所示:

process ---> payload <---- additional

(箭头代表参考文献)

然后你做到了:

process.getPayload().put("additionalData",additional);

这会添加到负载中,一个指向 additional 的新引用。注意这是如何创建一个循环的:

process ---> payload <---- additional
                |               ^
                |_______________|

这很好,直到您尝试打印 payload 的内容。它的值之一是additional所以additional的内容也需要打印,additional的值之一是payload,所以payload的内容被打印再次,循环继续......不幸的是,为 Map 编写 toString 方法的人没有写任何东西来检测这个。

putAll另一方面,

Copies all of the mappings from the specified map to this map.

因此,additional.putAll(process.getPayload()); 不会使 additional 引用 payload。相反,它只是将有效载荷具有的任何键和值添加到 additional.

此外,如果您创建一个包含有效负载的所有键和值的新映射,并使用 put.[=35 将其添加到 additional,它也不会创建循环=]

additional.put("exampleData", new HashMap<>(process.getPayload()));

而不是引用 payload,另外将引用新地图:

process ---> payload        additional ----> a copy of payload
                |               ^
                |_______________|