我目前正在制作一个自定义序列化程序作为项目的一部分,在这里我也需要序列化引用,这意味着如果两个字段在序列化之前引用同一个项目,它们也应该在反序列化之后。
为此,我使用HashMap,将每个对象映射到一个ID,我可以将其用作序列化的每个对象的属性,同时跟踪已经序列化的对象。我偶然发现了一些问题。
似乎java HashMap只检查键上的相等性,而不是它们是否是相同的引用。例如,在下文中,变量b最终为真:
HashMap<Object, Integer> map = new HashMap<Object, Integer>();
LinkedList<Object> ll1 = new LinkedList<Object>();
LinkedList<Object> ll2 = new LinkedList<Object>();
map.put(ll1, 5);
boolean b = map.containsKey(ll2);
有时候结果根本没有意义。在这里,b也是如此:
HashMap<Object, Integer> map = new HashMap<Object, Integer>();
LinkedList<Object> ll1 = new LinkedList<Object>();
Stack<Object> stack = new Stack<Object>();
map.put(ll1, 5);
boolean b = map.containsKey(stack);
我想要的是ContainsKey方法,不仅要调用equals方法,还要使用'==' - 运算符检查引用是否相同。我可以这样做而无需查看整个密钥集吗?
提前致谢
答案 0 :(得分:5)
Map接口的常规合同是,如果两个键都为null,或者它们不为null且a.equals(b)
,则认为它们是相等的。除非密钥类的==
方法的实现执行此操作,否则它不会使用equals
进行比较。
LinkedList
和Stack
个对象相同的原因是因为它们都实现了List
接口,List.equals
的定义是两个列表相等具有相同的大小,并以相同的顺序包含相同的对象。因为它们都是空的,所以它们是“平等的”。
我相信你正在寻找IdentityHashMap
。它故意违反Map接口的合同,仅使用==
,而不是Object.equals()
来比较对象。同样,对于哈希码,它使用System.identityHashCode
而不是任何被覆盖的Object.hashCode()
。