Java hashCode 随时间变化(不是由于字段)
Java hashCode changes over time (not due to fields)
根据 hashCode
/equals
合同,如果两个对象相等,则必须具有相同的 hashCode
- 至少我是这样知道的。考虑以下实现:
package Happy;
import java.time.LocalDate;
class MyClass
{
private int id;
public int getId()
{
return id;
}
public MyClass(int id)
{
this.id = id;
}
public int hashCode()
{
return LocalDate.now().getYear() + getId();
}
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyClass other = (MyClass) obj;
if (hashCode() != other.hashCode())
return false;
return true;
}
}
public class HappyNewYear
{
public static void main(String[] args) {
MyClass my = new MyClass(0);
if (my.hashCode() != my.hashCode()) System.out.println("Happy New Year!");
}
}
稍作修改,我们可以得到一个不那么极端的变体:
public int hashCode()
{
return return (int) (System.nanoTime() + getId());
}
我测试了它(虽然没有使用 getYear
),条件为真(hashCodes
不相等)。
如果 hashCode
随着时间的推移发生变化,即使对象的字段未修改,这是否合法? 我找不到有关此特定实现的任何资源。 我知道集合的问题,但我的问题是根据 contract/spec.[=21,hashCode 实现是否合法 =]
PS: 是一道挑战题,我回答说不合法,但我不确定,因为我第一次看代码,equals
和hashCode
是满足简单契约。
由于hashcode是用来放置然后查找存储在hashmaps中的对象,因此hashcode随时间变化的class将无法在hashmap中使用。
我认为如果.equals
方法失败了,那么.hashcode
应该也会失败。
也就是说,如果两个对象昨天被认为是相等的,但现在它们不相等,那么它很可能会产生比它解决的问题更多的问题,因为就对象而言,none它的领域发生了变化。 (例如,想想 运行 几天的系统)。
我建议您让 .hashcode()
依赖于对象本身,而不是会改变 并且在对象之外的东西 。如果这不是一个选项,您将需要大量记录。
这是合法的(编译器不会抱怨)但你不应该这样做。 HashCode
应该是一致的(returns 给定相同键的相同整数值)。
the hashCode
method must consistently return the same integer
你的hashCode
恰恰相反
根据 hashCode
/equals
合同,如果两个对象相等,则必须具有相同的 hashCode
- 至少我是这样知道的。考虑以下实现:
package Happy;
import java.time.LocalDate;
class MyClass
{
private int id;
public int getId()
{
return id;
}
public MyClass(int id)
{
this.id = id;
}
public int hashCode()
{
return LocalDate.now().getYear() + getId();
}
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyClass other = (MyClass) obj;
if (hashCode() != other.hashCode())
return false;
return true;
}
}
public class HappyNewYear
{
public static void main(String[] args) {
MyClass my = new MyClass(0);
if (my.hashCode() != my.hashCode()) System.out.println("Happy New Year!");
}
}
稍作修改,我们可以得到一个不那么极端的变体:
public int hashCode()
{
return return (int) (System.nanoTime() + getId());
}
我测试了它(虽然没有使用 getYear
),条件为真(hashCodes
不相等)。
如果 PS: 是一道挑战题,我回答说不合法,但我不确定,因为我第一次看代码,hashCode
随着时间的推移发生变化,即使对象的字段未修改,这是否合法? 我找不到有关此特定实现的任何资源。 我知道集合的问题,但我的问题是根据 contract/spec.[=21,hashCode 实现是否合法 =]
equals
和hashCode
是满足简单契约。
由于hashcode是用来放置然后查找存储在hashmaps中的对象,因此hashcode随时间变化的class将无法在hashmap中使用。
我认为如果.equals
方法失败了,那么.hashcode
应该也会失败。
也就是说,如果两个对象昨天被认为是相等的,但现在它们不相等,那么它很可能会产生比它解决的问题更多的问题,因为就对象而言,none它的领域发生了变化。 (例如,想想 运行 几天的系统)。
我建议您让 .hashcode()
依赖于对象本身,而不是会改变 并且在对象之外的东西 。如果这不是一个选项,您将需要大量记录。
这是合法的(编译器不会抱怨)但你不应该这样做。 HashCode
应该是一致的(returns 给定相同键的相同整数值)。
the
hashCode
method must consistently return the same integer
你的hashCode
恰恰相反