当我们多次运行应用程序时,为对象获取唯一且相同的哈希码的算法

时间:2010-11-12 05:44:40

标签: java hashcode

我正在使用Java。我想知道,当我将多次运行应用程序时,任何可用的算法都会给我一个唯一且相同的哈希码,以避免哈希码的冲突。

我知道对于类似对象,jvm返回相同的哈希代码,对于不同的对象,它可能会返回相同或不同的哈希代码。我想要一些有助于为每个对象生成唯一哈希码的逻辑。

unique意味着一个对象的哈希码不应该与任何其他对象的哈希码冲突。同样意味着当我多次运行应用程序时,它应该返回相同的哈希码,不管它以前返回的是什么

3 个答案:

答案 0 :(得分:4)

Java中的默认哈希码函数可能会为每个JVM调用返回不同的哈希码,因为它能够使用对象的内存地址,对其进行修改并返回它。

然而,这不是很好的编码实践,因为相同的对象应该总是返回相同的哈希码!请阅读hash code contract了解详情。 Java中的大多数类都已经实现了一个哈希码函数,它在每次JVM调用时返回相同的值。

简化:所有可能存储在某个集合中的数据保存对象应该具有equals和hashcode实现。如果使用Eclipse或任何其他合理的IDE进行编码,则可以使用自动创建函数的向导。

虽然我们在这里:恕我直言的好习惯也是实现Comparable<T>接口,所以你也可以使用SortedSets和TreeMaps中的对象。

我们现在就是这样:如果其他人应该使用您的对象,请不要忘记SerializableCloneable

答案 1 :(得分:1)

  

唯一意味着一个对象的哈希码不应与任何其他对象的哈希码冲突。同样意味着当我多次运行应用程序时,它应该返回相同的哈希码,无论它之前返回的是什么。

出于多种原因,不可能满足这些要求:

  • 无法保证哈希码是唯一的。无论您在类hashcode方法中执行什么操作,其他一些类hashcode方法都可能为某个实例提供一个与您的某个实例的哈希码相同的值。

  • 不可能保证哈希码在应用程序运行中是唯一的,即使只是针对您的类的实例。

第二个要求理由。创建唯一哈希码的方法是执行以下操作:

    static HashSet<Integer> usedCodes = ...
    static IdentityHashMap<YourClass, Integer> codeMap = ...

    public int hashcode() {
        Integer code = codeMap.get(this);
        if (code == null) {
            code = // generate value-based hashcode for 'this'
            while (usedCode.contains(code)) {
                code = rehash(code);
            }
            usedCodes.add(code);
            codeMap.put(this, code);
        }
        return code;
    }

这为哈希码提供了所需的唯一性属性,但不保证相同属性...除非应用程序始终以相同的顺序生成/访问所有对象的哈希码。

实现此功能的唯一方法是以合适的形式保留usedCodecodeMap数据结构。甚至(仅)将唯一的哈希码存储为持久对象的一部分是不够的,因为在读取具有哈希码的现有对象之前,应用程序可能会重新发出哈希码给新创建的对象。

最后,应该注意的是,您必须小心在解决方案中的任何位置使用标识哈希码。标识哈希码在应用程序的不同运行中不是唯一的。实际上,如果任何输入存在差异,或者存在任何非确定性,则每次运行应用程序时,给定对象很可能具有不同的标识哈希码值。

关注

  

假设您在数据库中存储了数百万个URL。在检索这些网址时,我想生成唯一的哈希码,以便更快地进行搜索。

您需要将哈希码存储在表的单独列中。但鉴于上面讨论的限制,我不知道这将如何使搜索更快。基本上,您必须在数据库中搜索URL,以便计算出其唯一的哈希码。

我认为你最好使用非常小的概率的哈希码。如果你使用足够好的“加密”散列函数和足够大的散列大小,你可以(在理论上)使碰撞概率任意小......但不能为零。

答案 2 :(得分:0)

根据我对你的问题的理解......

如果它是您的自定义对象,则可以覆盖hashcode方法(以及equals)以根据类的实例变量获取一致的哈希码。你甚至可以返回一个常量哈希码,它仍然会满足hascode契约。