Java 当我为同一个对象返回不同的哈希代码时,为什么HashMap会覆盖现有对象?
驱动程序代码:Java 当我为同一个对象返回不同的哈希代码时,为什么HashMap会覆盖现有对象?,java,java-8,Java,Java 8,驱动程序代码: import java.util.HashMap; import java.util.Map; class Geek { public String name; public int id; Geek(String name, int id) { this.name = name; this.id = id; } @Override public boolea
import java.util.HashMap;
import java.util.Map;
class Geek
{
public String name;
public int id;
Geek(String name, int id)
{
this.name = name;
this.id = id;
}
@Override
public boolean equals(Object obj)
{
// checking if both the object references are
// referring to the same object.
if(this == obj)
return true;
// it checks if the argument is of the
// type Geek by comparing the classes
// of the passed argument and this object.
// if(!(obj instanceof Geek)) return false; ---> avoid.
if(obj == null || obj.getClass()!= this.getClass())
return false;
// type casting of the argument.
Geek geek = (Geek) obj;
// comparing the state of argument with
// the state of 'this' Object.
System.out.println("equals method ....."+(geek.name == this.name && geek.id == this.id));
return (geek.name == this.name && geek.id == this.id);
}
int counter = 0;
@Override
public int hashCode()
{
// We are returning the Geek_id
// as a hashcode value.
// we can also return some
// other calculated value or may
// be memory address of the
// Object on which it is invoked.
// it depends on how you implement
// hashCode() method.
++counter;
System.out.println("counter ::>>> "+counter);
return counter;
}
publicstaticvoidmain(字符串[]args)
{
Map Map=newhashmap();
//创建Geek类的对象。
极客g1=新极客(“aa”,1);
极客g2=新极客(“aa”,1);
map.put(g1,g1.id);
map.put(g2,g2.id);
图.forEach((k,v)->{
System.out.println(“key=“+k+”\n value=“+v”);
});
/*否则
System.out.println(“两个对象不相等”)*/
}
在这里,我覆盖了hashCode()
方法,但映射仍然只包含一个对象,即g2
。既然我的hashcode每次返回一个不同的整数,为什么HashMap不存储两个对象呢
即使我的
equals()
方法对同一个对象返回true,为什么HashMap不存储两个对象?有人能在这方面指导我吗?您的计数器
变量是一个实例变量,因此每个极客
实例都将其初始化为0
。因此,当您将g1
和g2
放在Map
中时,它们都具有与1
相同的hashCode()
,并且被HashMap
视为相同,因为它们基于equals
实现彼此相等
如果将计数器
更改为静态
,则极客
的两个实例将获得不同的hashCode()
,它们将存储在单独的地图条目中
也就是说,您的hashCode()
实现非常糟糕。如果对同一实例多次调用hashCode()
,每次都会得到不同的结果!这意味着,如果您尝试在映射中放置g1
两次,它可能会放置两次,因为第二次put
将看到不同的hashCode()
,因此会在不同的存储桶中搜索密钥。hashCode()
函数在同一对象实例上多次调用时不得更改。不能每次调用时都生成一个新值,现在可以通过递增计数器来实现
根据:
在Java应用程序的执行过程中,每当在同一对象上多次调用hashCode方法时,只要没有修改对象上的equals比较中使用的信息,hashCode方法必须始终返回相同的整数。从应用程序的一次执行到同一应用程序的另一次执行,该整数不必保持一致
虽然这是正确的,但它不能解释OP遇到的行为。你没有明白我的问题。试着按照我的要求去理解它。不要告诉我equals()和hashcode的约定。我很清楚。我想问的是-为什么hashmap没有存储2个对象?你没有理解我的问题。试着按照我的要求去理解它。不要告诉我equals()和hashcode的约定。我很清楚。我想问的是-为什么hashmap没有存储2个对象?@Vikasnaik你打算在其他答案下发表这篇评论吗?我没有告诉你equals和hashcode的约定。@Vikasnaik正如我所解释的,hashcode()
为Geek
的两个实例返回1
(第一次为这两个实例调用hashcode)。因此,HashMap
将它们存储在同一个bucket中,由于它们相等,第二个将覆盖第一个。@Vikasnaik也许您应该替换map.put(g1,g1.id);map.put(g2,g2.id)带有System.out.println(g1.hashCode())的code>;System.out.println(g2.hashCode())代码>以更好地理解我的答案。@LewBloch这不是一个保证的行为。使用哈希代码是一种性能优化,仅此而已。您需要保持hashCode和equals同步,这样它是否使用哈希代码就无关紧要了。虽然在本例中,您的hashCode
方法实际上会为不同的对象返回相同的哈希代码,如果对象恰好落在同一个哈希表存储桶中,HashMap
不可能使用equals
来比较不同哈希代码的对象。你故意试图破坏这里的地图,所以你不应该期望逻辑行为。
public static void main (String[] args)
{
Map<Geek, Integer> map = new HashMap<>();
// creating the Objects of Geek class.
Geek g1 = new Geek("aa", 1);
Geek g2 = new Geek("aa", 1);
map.put(g1, g1.id);
map.put(g2, g2.id);
map.forEach((k,v) -> {
System.out.println("key = "+k + "\n value = "+v);
});
/* else
System.out.println("Both Objects are not equal. "); */
}