У меня есть класс ниже, который я использую из многопоточного приложения, поэтому я сделал его потокобезопасным. Просто для простоты я показываю здесь только несколько полей, чтобы продемонстрировать проблему.
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();
Как я могу решить эту проблему? Я хочу сделать свою карту неизменной, но я также хочу инициализировать обязательные поля, и я могу сделать это только в конструкторе класса ClientKey
. И это вызывает исключение при клонировании объекта ClientKey
.
ClientKey clonedKey = new ClientKey.Builder(keys).processName("hello").build();
вызовет исключение, поскольку у вас даже нет ключаis_clientid
. Где происходит следующая строка в вашем коде? - person jamesw1234   schedule 17.12.2016this.parameterMap = builder.parameterMap.build();
, но только если я пытаюсь клонировать объектkeys
в новыйclonedKey
- person   schedule 17.12.2016ClientKey
будет вызываться снова, а затем он попытается снова вставить тот жеis_clientid
в карту, и поэтому он выдает исключение. - person   schedule 17.12.2016builder
? - person jamesw1234   schedule 17.12.2016build()
в моем шаблоне строителя. Я предполагаю, что эта ошибка связана с тем, что вы не можете дважды вставить один и тот же ключ в Guava ImmutableMap? - person   schedule 17.12.2016build()
на самом деле не создает экземплярbuilder
. В вашем кодеbuilder.parameterMap.build();
гдеbuilder
создается первый экземпляр - person jamesw1234   schedule 17.12.2016