我定义了以下类,试图使“IamImmutable.class”不可变。但是当我在初始化 IamImmutable 后更改 TestingImmutability.class 中的 hashmap 值时,更改适用于 Hashmap。即使我们用 new HashMap(old) 实例化它,Hashmap 也会引用同一个对象。我需要使实例中的 Hashmap 不可变。我也尝试过迭代和复制值,但这不起作用。谁能建议如何进行?
package string;
import java.util.HashMap;
import java.util.Map.Entry;
public final class IamImmutable {
private int i;
private String s;
private HashMap<String, String> h;
public IamImmutable(int i, String s, HashMap<String, String> h) {
this.i = i;
this.s = s;
this.h = new HashMap<String, String>();
for (Entry<String, String> entry: h.entrySet()) {
this.h.put((entry.getKey()), entry.getValue());
}
}
public int getI() {
return i;
}
public String getS() {
return s;
}
public HashMap<String, String> getH() {
return h;
}
}
还有一个测试:
package string;
import java.util.HashMap;
import java.util.Map.Entry;
public class TestingImmutability {
public static void main(String[] args) {
int i = 6;
String s = "!am@John";
HashMap<String, String> h = new HashMap<String, String>();
h.put("Info1", "!am@John");
h.put("Inf02", "!amCrazy6");
IamImmutable imm = new IamImmutable(i, s, h);
h.put("Inf02", "!amCraxy7");
System.out.println(imm.getS() + imm.getI());
for (Entry<String, String> entry: h.entrySet())
System.out.println(entry.getKey() + " --- " + entry.getValue());
}
}
Expected output:
!am@ John6 Inf02---!amCrazy6 Info1---!am@ John
Actual output:
!am@ John6 Inf02---!amCraxy7 Info1---!am@ John
最佳答案
你的测试是错误的,你正在检查 h
的内容,你传递给构造函数并随后修改的映射,而不是 imm.getH()
.如果你检查正确的 map
for (Entry<String, String> entry : imm.getH().entrySet())
System.out.println(entry.getKey() + " --- " + entry.getValue());
一切看起来都很好:
!am@John6
Info1 --- !am@John
Inf02 --- !amCrazy6
所以您的 IamImmutable
构造函数已经很好,以后对传递给构造函数的原始映射的任何更改都不会影响您在构造时创建的副本。您还可以使用 other HashMap constructor你提到过,它的可读性稍强一些:
public IamImmutable(int i, String s, HashMap<String, String> h)
{
this.i = i;
this.s = s;
this.h = new HashMap<String, String>(h);
}
这也能正常工作。
另一个问题是 getH()
将内部 map 的引用传递给世界,如果世界更改该引用,事情就会出错。一个简单的解决方法是应用您已经在 getH()
的构造函数中使用的相同复制技巧:
public HashMap < String, String > getH() {
return new HashMap<String,String>(h);
}
或者在返回之前装饰内部 map :
public Map<String, String> getH() {
return Collections.unmodifiableMap(h);
}
考虑使用 ImmutableCollections in the guava library反而。他们完成了与此代码相同的工作,但更多地考虑了效率和易用性。构造时的完整副本和获取 map 的操作很笨重,如果我们知道它无论如何都不会被修改,那么标准的底层 HashMap 将进行毫无意义的修改检查。
关于java - 使用 hashmap 的不可变类示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29740709/