【问题标题】:Find objects without hashcode查找没有哈希码的对象
【发布时间】:2018-07-24 02:30:20
【问题描述】:

我需要让程序更具确定性:即重构它,以减少对运行的依赖。

一个可能的不确定原因是:使用 HashMap/HashSet/etc 和使用默认对象 hashCode() 的键。

关键是默认 Object 的 hashCode() 使用对内存中对象的实际引用,这意味着每次重新运行它都可能不同。

有没有一种好方法可以打印出所有没有重新定义 hashCode() 方法并被其哈希使用的类?

代码库非常庞大(高达数百 MB 的代码),有很多内部类、接口、抽象类等。找出需要关注的映射/集合本身就是一个问题

【问题讨论】:

  • 您可以编写 Java 代码,将所有 .java 文件作为测试文件读取并搜索 public int hashCode()。
  • 如果要使用您的代码库,建议使用 LinkedHashMap/Set 而不是 HashMap 等。这些至少以可预测的顺序迭代。
  • 看看Reflections library。我不知道它是否满足您的特定用例,但至少它会是一个很好的近似值。
  • Object.hashCode 多年来一直没有使用对象的内存地址,尽管文档仍然提到它。相反,它使用伪随机数生成器。由于伪随机状态取决于调用了哪些对象以及调用了多少个对象 hashCode,这可能会导致不确定的行为。
  • Intellij 的“结构搜索”可能可以用于此。

标签: java collections java-8 java-7 deterministic


【解决方案1】:

您的前提“我需要使程序更具确定性”存在一个根本缺陷。要么,您的程序是正确的,要么它已损坏。如果它依赖于未指定的属性,那么它就被破坏了,试图让它“少一点破坏”是没有意义的。你必须修复错误的部分。

例如,无论您如何实现 hashCode() 方法,依赖 HashMap 或 HashSet 的迭代顺序总是被破坏。正如this answer 所证明的那样,尽管包含的元素具有@ 987654322@.

因此,在类的 hashCode() 方法中混杂并不会改进您的应用程序,您必须修复错误地依赖返回的数字(并且可能依赖于其他未指定的实现细节)的部分。

【讨论】:

  • 我喜欢这个! 试图让它不那么破碎是没有意义的,真的应该印在我的团队领导脸上)
【解决方案2】:

您的问题中有一个有缺陷的假设:HashMap 或 HashSet 不保证以任何特定顺序返回其项目,无论 Object::hashCode 的实现如何。如果您需要以特定顺序进行迭代,您应该查看Map 和Set 的实现,而不是寻求hashCode 来提供确定性,确实 提供保证的迭代顺序。 p>

一个例子是java.util.LinkedHashMap,它和HashMap 一样,只是保证项目按照它们放入地图的顺序返回。 java.util.LinkedHashSet 是类似的,但作为 Set。如果您需要不同的顺序,java.util.TreeMap 和 java.util.TreeSet 可以使用您想为您的结构提供自定义确定性顺序的任何 Comparator 构造(默认情况下使用自然排序顺序)。

【讨论】:

  • 感谢回复,将所有 Hash 集合替换为其他类型会导致性能下降,并使下一个版本的结果与当前版本更加不同。关键是如何找出需要重构的案例。
猜你喜欢
  • 2021-07-01
  • 2012-03-10
  • 1970-01-01
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-11-11
  • 2020-04-27
  • 2015-11-20
相关资源
最近更新 更多