Java hashCode,人工字段?

时间:2015-02-15 11:05:57

标签: java field hashcode

想象一下以下问题:

    // Class PhoneNumber implements hashCode() and equals()
PhoneNumber obj = new PhoneNumber("mgm", "089/358680");
System.out.println("Hashcode: " +
    obj.hashCode());  //prints "1476725853"

// Add PhoneNumber object to HashSet
Set<PhoneNumber> set = new HashSet();
set.add(obj);

// Modify object after it has been inserted
obj.setNumber("089/358680-0");

// Modification causes a different hash value
System.out.println("New hashcode: " +
    obj.hashCode()); //prints "7130851"

// ... Later or in another class, code such as the following
// is operating on the Set:

// Unexpected Result!
// Output: obj is set member: FALSE
System.out.println("obj is set member: " +
    set.contains(obj));

如果我有一个课程,我希望我的所有字段都可以编辑,并且仍然可以使用set / hashCode。在创建对象时设置的类中创建一个人工不可编辑的字段会是一个好主意吗?例如,以ms为单位的当前时间。当我获得该字段时,我可以将哈希码基于它,我仍然可以编辑所有&#34;真实&#34;领域。这是个好主意吗?

3 个答案:

答案 0 :(得分:3)

我坚信你提出了一个不好的用例:如果你需要修改Set中的对象,你一定要删除旧的并重新添加新的(或使用另一个java.util.Collection })。以你的例子为例:

Set<PhoneNumber> set = new HashSet();
set.add(obj);

// Modify object after it has been inserted
set.remove(obj);
obj.setNumber("089/358680-0");
set.add(obj);

hashCode的全部目的是创建一个类似对象的桶来减少搜索空间,因此它应该是不可变的但对你有用(如果使用人工场,你如何找到对象)你的集合如何?如果没有任何类型的持久性存储,你如何检索这个人工字段 - 数据库中的id是使用人工字段IMHO的一个例外。

解释

的含义
  

hashCode的全部目的是创建一个类似的桶   减少搜索空间的对象

查看此示例代码:http://ideone.com/MJ2MQT。我(错误地)创建了具有相同哈希码的对象,然后将它们添加到一个集合中;正如所料,该集合包含它们,因为哈希码用于检索碰撞的元素,然后调用equals方法来解决此冲突。碰撞(读different objects which return same hash code)是不可避免的,正确设计的哈希码函数的目标是尽可能减少它们。

答案 1 :(得分:1)

将可变对象存储在哈希集中,或者将它们用作哈希映射中的键,绝对不是不是一个好主意,正是因为您在代码中进行了说明。

另一方面,定义一个充当对象的ID的人为数字会破坏首先使用哈希码的目的,因为它无法帮助您找到等于通过将搜索限制为具有相同哈希码的对象来获取给定对象。

事实上,您的解决方案与从#34;人工哈希码&#34;构建Map<Integer,PhoneNumber>没有什么不同。到你的可变PhoneNumber对象。如果通过关联查找对象是您所需要的,那么从人工ID到可变对象的HashMap是可行的方法。

答案 2 :(得分:0)

为数据对象提供唯一标识符通常是有意义的,特别是如果您将它们保存在某个数据库中。它允许您轻松实现equalshashCode,这只取决于此单一标识符。

我不确定ms的当前时间。将是最好的选择,但你一定要产生一些独特的ID。