我想维护一个对象列表,这样列表中的每个对象都是唯一的。我也想在一个点上检索它。对象有数千个,我无法修改其源代码以添加唯一ID。 hascodes也不可靠。
我的方法是利用地图的关键唯一性。 假设维护一张地图:
HashMap<Object,int> uniqueObjectMap
。
我将使用键添加对象以及将随机int设置为值。但是,当用作密钥时,java如何确定对象是否是唯一的?
说,
List listOne;
List listTwo;
Object o = new Object;
listOne.add(o);
listTwo.add(o);
uniqueObjectMap.put(listOne.get(0),randomInt()); // -- > line 1
uniqueObjectMap.put(listTw0.get(0),randomInt()); // --> line 2
第2行是否会给出唯一的密钥违规错误,因为两者都指的是同一个对象o?
修改
那么unqiueObjectMap.containsKey(listTwo.get(0))
是否会返回true?对象如何确定在这里相等?是通过现场比较来完成的吗?我可以依赖它来确保在地图中只保留任何类型的对象的一个副本作为键吗?
答案 0 :(得分:3)
第2行是否会给出唯一的密钥违规错误,因为两者都指的是同一个对象o?
- 否即可。如果发现密钥已经存在,那么将使用新的覆盖其值。
接下来,HashMap有一个单独的hash()
方法,将补充哈希函数应用于给定的hashCode(密钥对象),以防止质量差的哈希函数。
答案 1 :(得分:2)
通过调用Object
&#39; hashcode()
函数来实现此目的。
默认实现大致相当于对象的唯一标识符(很像内存地址);但是,有些对象是按值进行比较的。如果处理按值比较对象,将覆盖hashcode()
以根据值计算数字,以便两个相同的值产生相同的hashcode()
数字。
对于基于散列的集合项,put(...)
操作可以将放在原始位置。简而言之,如果两个对象产生相同的hashcode()
和一个肯定的equals(...)
结果,那么操作将假定它们在所有实际目的中都是相同的对象。因此,put可以用新的替换旧的,或者什么也不做,因为对象被认为是相同的。
它可能不会在同一个&#34;地点&#34;中存储两个副本。因为在同一位置存储两份副本毫无意义。因此,集合只包含一个副本,映射键也是如此;但是,列表可能包含两个副本,具体取决于您添加第二个副本的方式。
答案 2 :(得分:2)
这里的对象如何确定相等? 通过使用Object类的equals和Hashcode函数。
字段比较字段是否已完成? 不,如果你不实现equals和hashcode,java会比较你对象的引用。
我可以依赖它来确保地图中只保留任意类型对象的一个副本作为密钥吗? 否。
使用Set
是比使用Map
更好的方法,因为它会删除自己的重复项,但在这种情况下它不会起作用,因为Set
确定重复项的方式与Map
使用密钥进行操作。
答案 3 :(得分:1)
如果您将引用same
,那么它会not throw an error
,因为当HashMap get same key
时,它的相关值将为overwrite
。
如果HashMap
中存在相同的密钥,那么它将是overwritten
。
如果要检查密钥或值是否已存在,则可以使用:
containsKey()
和containsValue()
。
前:
hashMap.containsKey(0);
如果名为true
的密钥已存在0
,则会返回false
。
答案 4 :(得分:0)
通过使用hash(key.hashCode())
获得哈希码值
HashMap has an inner class Entry with attributes
final K key;
V value;
Entry<K ,V> next;
final int hash;
哈希值用于计算数组中用于存储Entry对象的索引,在某些情况下,两个不相等的对象可以具有相同的哈希值。
条目对象以链接列表形式存储,如果发生冲突,所有具有相同哈希值的条目对象都存储在相同的Linkedlist中,但是equal方法将测试真实相等性。这样,HashMap可以确保键的唯一性。