【问题标题】:Performance warning in Guava ImmutableMapGuava ImmutableMap 中的性能警告
【发布时间】:2013-03-16 21:15:17
【问题描述】:

在 Guava 的 ImmutableMap 的 javadocs 中它说:

性能说明:与 HashMap 不同,ImmutableMap 没有针对 具有慢 Object.equals(java.lang.Object) 或 Object.hashCode() 实现。您可以通过以下方式获得更好的性能 让你的元素类型缓存它自己的哈希码,并通过使用 的缓存值以使慢速等于算法短路。

所以我的第一个问题是如何知道我的元素是否具有缓慢的 .equals 或 .hashCode 实现?在我的具体实例中,我使用 java Enum 作为我的键,因此它具有 .equals 和 .hashCode 的有效默认实现,对吗? (我假设这些值的实现是无关紧要的,只要您不使用值的值访问地图。)

我的第二个问题是“让你的元素类型缓存它自己的哈希码”是什么意思!谷歌搜索我似乎无法找到你将如何做到这一点的例子。我想这可能意味着您最终会在哈希码中使用哈希码?所以我进入哈希码桶,然后 .equals 方法在其中使用第二组哈希码?

【问题讨论】:

    标签: java guava


    【解决方案1】:

    我使用 java Enum 作为我的键,所以它具有 .equals 和 .hashCode 的有效默认实现,对吗?

    equals 或 hashcode 都没有被覆盖,因此它几乎不会更快(即 equals 返回 this == other)。

    我的第二个问题是“让你的元素类型缓存它自己的哈希码”是什么意思!

    您可以使用下面的代码,以避免多次计算 - 如果您这样做,您需要确保:

    • 哈希码是不变的(即在实例的整个生命周期内不能更改)
    • 您的 hashcode 方法是线程安全的(例如,可以使用局部变量或更简单地使 hash 易失性来完成)。
    class MyClass {
        private int hash;
    
        public int hashcode() {
            int hash = this.hash;
            if (hash == 0) {
                hash = calculateIt();
                this.hash = hash;
            }
            return hash;
        }
    }
    

    【讨论】:

    • 如果对象是不可变的并且经常调用hashcode() / equals(),你甚至可以在对象的构造过程中计算hashcode,不再担心线程安全。
    • @FrankPavageau 绝对 - 这确实更容易,更安全。
    【解决方案2】:

    如果您的密钥是 Enum,那么这对您来说不是问题。

    他们谈论的缓存哈希码是这样的:

    private volatile int hashCode = -1;
    
    @Override
    public int hashCode() {
      if ( hashCode == -1 ) {
        hashCode = longCalculation();
      }
      return hashCode;
    }
    

    【讨论】:

    • 当然,您必须注意 -1 不是有效的哈希值。 java.lang.String 有这个问题:有些字符串每次都会重新计算它们的哈希值。
    • @assylias - 你是对的 - 在一定程度上。实际上它安全的,但是如果多个线程同时请求hashCode,则可以多次调用longCalculation。如果这是一个关键问题,那么我肯定会在多线程环境中为这种方法付出更多努力。但是,它确实清楚地表明了我的观点。
    • 那么他们的意思是你将哈希码保存为实例变量,这样你就不需要重复计算了?基本上,您会牺牲一些内存(额外的实例变量)来通过缓存值来提高性能。
    • @CorayThan - 是的!这就是缓存值的含义。
    【解决方案3】:

    我知道这是一个非常古老的问题,但对于像我一样来到这里的人 - 如果您的密钥是枚举,您真的应该使用 EnumpMap

    【讨论】:

      猜你喜欢
      • 2012-03-18
      • 2014-03-22
      • 1970-01-01
      • 1970-01-01
      • 2018-09-17
      • 2013-03-23
      • 2012-09-16
      • 2016-01-07
      • 2021-04-19
      相关资源
      最近更新 更多