我正在使用HashMap
而我无法直接回答get()
方法在碰撞情况下的工作原理。
假设n > 1
个对象放在同一个键中。它们存储在LinkedList
中吗?它们是否被覆盖,以便只存在那个键中的最后一个对象?他们正在使用其他一些碰撞方法吗?
如果将它们放在LinkedList
中,有没有办法检索整个列表?如果没有,是否有其他内置的 Java 地图,我可以在其中执行此操作?
就我的目的而言,单独的链接是理想的,就好像存在冲突一样,我需要能够查看列表并获取有关其中所有对象的信息。在 Java 中执行此操作的最佳方法是什么?
感谢您的帮助!
答案 0 :(得分:8)
documentation for Hashmap.put()明确指出,“将指定的值与此地图中的指定键相关联。如果地图以前包含该键的映射,则旧值将被替换”< / p>
如果您想要一个与密钥关联的对象列表,请将列表存储为值。
请注意,'collision'通常是指HashMap的内部工作,其中两个键具有相同的哈希值,而不是对两个不同的值使用相同的键。
答案 1 :(得分:7)
它们是否被覆盖,以便只存在该键中的最后一个对象?
是的,假设您使用相同的密钥放置多个值(根据Object.equals
,而不是Object.hashCode
。)Map.put
javadoc中指定的值:
如果地图以前包含该键的映射,则旧值将替换为指定的值。
如果你想将一个键映射到多个值,你可能最好使用像Guava的ListMultimap
,ArrayListMultimap
这样的东西,它将键映射到值列表。 (披露:我向Guava捐款。)如果你不能容忍第三方库,那么你真的需要Map<Key, List<Value>>
,尽管这可能有点笨拙。
答案 2 :(得分:3)
假设n&gt; 1个对象放在同一个键中。它们是否存储在链表中?它们是否被覆盖,以便只存在那个键中的最后一个对象?他们正在使用其他一些碰撞方法吗?
同一个密钥可能有单个实例,因此最后一个覆盖前一个
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("a", 2);// it overrides 1 and puts 2 there
链接来自不同键的相同哈希值
查看强>
答案 3 :(得分:0)
引用:“假设n&gt; 1个对象放在同一个键中。它们是否存储在链表中?它们是否被覆盖,以便只存在该键中的最后一个对象?它们是否正在使用其他对象?碰撞方法?“
是的,如果hashmap包含此键下的内容,它将覆盖它。
您可以实现自己的类来处理或更简单地使用HashMap&gt;其中K是您的关键对象,V是对象值。 请记住,当您执行map.get(K)时,使用最后一个解决方案将检索List或您选择的实现(即:ArrayList),以便您可以使用此实现的所有方法,并且可能满足您的要求。例如,如果你使用了Arraylist,你就有了size,trimToSize,removeRange等等。
答案 4 :(得分:0)
java中哈希的冲突解决方案不是基于链接。据我了解,JDK使用双散列,这是开放寻址的最佳方式之一。因此,没有列表与哈希槽相关联。
您可以将散列函数解析为相同键的对象放入列表中,并且可以在表/映射中更新此列表。
package hashing;
import java.util.HashMap;
import java.util.Map;
public class MainAnimal {
/**
* @param args
*/
public static void main(String[] args) {
Animal a1 = new Animal(1);
Animal a2 = new Animal(2);
Map<Animal, String> animalsMap = new HashMap<Animal, String>();
animalsMap.put(a1,"1");
animalsMap.put(a2,"2");
System.out.println(animalsMap.get(a1));
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("a", 2);// it overrides 1 and puts 2 there
System.out.println(map.get("a"));
}
}
class Animal {
private int index = 0;
Animal(int index){
this.index = index;
}
public boolean equals(Object obj){
if(obj instanceof Animal) {
Animal animal = (Animal) obj;
if(animal.getIndex()==this.getIndex())
return true;
else
return false;
}
return false;
}
public int hashCode() {
return 0;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
在上面的代码中,我展示了两个不同的东西。
案例1 - 两个不同的实例解析为相同的hashkey 情况2 - 两个相同的实例充当两个不同条目的键。
动物实例,a1&amp; a2解析为相同的密钥。但它们并没有被覆盖。散列机制通过散列槽探测并将条目放在不同的插槽上。
对于第二种情况,键解析为相同的散列键,并且equals方法也满足。因此,重叠发生。
现在如果在动物类中我用这种方式覆盖equals方法 -
public boolean equals(Object obj){
// if(obj instanceof Animal) {
// Animal animal = (Animal) obj;
// if(animal.getIndex()==this.getIndex())
// return true;
// else
// return false;
// }
// return false;
return true;
}
重叠发生。行为就像使用相同的实例。由于a1和a2在同一个桶中,因此等于返回true。