gpt4 book ai didi

java - 具有相同键的多个条目不可变映射错误

转载 作者:行者123 更新时间:2023-11-29 08:39:45 25 4
gpt4 key购买 nike

我有一个在多线程应用程序中使用的构建器类,因此我已使其成为线程安全的。为简单起见,我在这里只显示几个字段来演示问题。

public final class ClientKey {
private final long userId;
private final int clientId;
private final String processName;
private final Map<String, String> parameterMap;

private ClientKey(Builder builder) {
this.userId = builder.userId;
this.clientId = builder.clientId;
this.processName = builder.processName;
// initializing the required fields
// and below line throws exception once I try to clone the `ClientKey` object
builder.parameterMap.put("is_clientid", (clientId == 0) ? "false" : "true");
this.parameterMap = builder.parameterMap.build();
}

public static class Builder {
private final long userId;
private final int clientId;
private String processName;
private ImmutableMap.Builder<String, String> parameterMap = ImmutableMap.builder();

// this is for cloning
public Builder(ClientKey key) {
this.userId = key.userId;
this.clientId = key.clientId;
this.processName = key.processName;
this.parameterMap =
ImmutableMap.<String, String>builder().putAll(key.parameterMap);
}

public Builder(long userId, int clientId) {
this.userId = userId;
this.clientId = clientId;
}

public Builder parameterMap(Map<String, String> parameterMap) {
this.parameterMap.putAll(parameterMap);
return this;
}

public Builder processName(String processName) {
this.processName = processName;
return this;
}

public ClientKey build() {
return new ClientKey(this);
}
}

// getters
}

下面是我制作 ClientKey 的方法,它工作正常。

Map<String, String> testMap = new HashMap<String, String>();
testMap.put("hello", "world");
ClientKey keys = new ClientKey.Builder(12345L, 200).parameterMap(testMap).build();

现在,当我尝试如下所示克隆 keys 对象时,它会抛出异常。

ClientKey clonedKey = new ClientKey.Builder(keys).processName("hello").build();

它抛出异常并显示错误消息:java.lang.IllegalArgumentException: Multiple entries with same key: is_clientid=true and is_clientid=true

builder.parameterMap.put("is_clientid", (clientId == 0) ? "false" : "true");
// from below line exception is coming
this.parameterMap = builder.parameterMap.build();

我该如何解决这个问题?我想让我的 map 不可变,但我也想用必填字段进行初始化,而且我只能在 ClientKey 类的构造函数中进行初始化。它在克隆 ClientKey 对象时抛出异常。

最佳答案

当你构造一个 ClientKey 时, "is_clientid" key 放在 map 上。因此,如果您调用 ClientKey.Builder(ClientKey)构造函数 putAll调用会将其复制到您的新 ImmutableMap.Builder实例。当您构建克隆的 ClientKey 时, ClientKey构造函数将再次尝试将相同的键添加到 map ,这会导致异常。

ImmutableMap.Builder本来可以用不同的方式写的,但事实并非如此。如果你想使用它,你将不得不忍受它。

一种解决方案是不复制带有 "is_clientid" 的条目新 key ImmutableMap.Builder在你的 Builder 的构造函数中.而不是 this.parameterMap = ImmutableMap.<String, String>builder().putAll(key.parameterMap);你写:

this.parameterMap = new ImmutableMap.Builder<>();
for (Map.Entry<String,String> entry : key.parameterMap.entrySet()) {
if (!"is_clientid".equals(entry.getKey()) {
this.parameterMap.put(entry.getKey(), entry.getValue());
}
}

另一个解决方案是不使用 Guava 的 ImmutableMap.Builder ,而是一个普通的 Java HashMap (当您尝试将重复键放入其中时,它不会抛出异常,旧条目会被简单地覆盖)。然后在你的ClientKey你写的构造函数:

this.parameterMap = Collections.unmodifiableMap(builder.parameterMap);

你也可以这样写:

this.parameterMap = ImmutableMap.copyOf(builder.parameterMap);

但这会制作 map 的完整副本,对于非常大的 map ,这可能需要一些时间。

结束语:如果您只想复制 ClientKey ,你不需要 builder ;惯用的 Java 将使用复制构造函数或 clone()方法(尽管有些人不鼓励使用后者)。

关于java - 具有相同键的多个条目不可变映射错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41195885/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com