【问题标题】:Custom hashcode/equals operation for HashMapHashMap 的自定义 hashcode/equals 操作
【发布时间】:2013-02-17 13:00:57
【问题描述】:

是否有 HashMap 类(或 Map 接口)的实现允许我使用备用哈希码和等于操作... 类似于如何使用 Collections.sort(list,comparator) 中的 Comparator 以多种方式对相同类型的集合进行排序。

如果可能,我想避免创建一个提供所需哈希码和等于操作的密钥包装器。


就我而言,我需要这样的情况之一:

在我的 Web 应用程序中,对于每个请求,我都会加载位置/ISP 和其他数据。 在代码的不同部分(在我的服务和存储库层中),我已经“最小化”了特定于其要求的缓存。

这是一个简化的代码示例:

class GeoIpData{
    private String countryName;
    private String state;
    private String city;
    private String isp;
    @Override
    public int hashCode() {
        //countryName hashCode
        //state hashCode
        //city hashCode
        //isp hashCode
    }
    @Override
    public boolean equals(Object obj) {
        // compare countryName
        // compare state
        // compare city
        // compare isp
    }
}

 Map<GeoIpData,#Type1> fullCache = ... //This cache needs to be unique per countryName,state,city and isp
 Map<GeoIpData,#Type2> countryCache = ... //This cache needs to be unique per countryName
 Map<GeoIpData,#Type2> ispCache = ... //This cache needs to be unique per countryName,isp

要实现这一点,上述 3 个映射需要 3 个不同的 hashcode 和 equals 方法。

fullCache:
hashCode -> GeoIpData.hashCode();
equals   -> GeoIpData.equals(Object obj);

countryCache:
hashCode -> {countryName hashCode }
equals   -> {compare countryName }

ispCache:
hashCode -> {countryName hashCode & isp hashCode }
equals   -> {compare countryName & compare isp hashCode }

【问题讨论】:

    标签: java hashmap equals hashcode overriding


    【解决方案1】:

    GNU Trove 允许您为特定的 TObjectHashingStrategy 提供您自己的哈希和等于 TCustomHashMap 的函数。

    【讨论】:

    • 嗨“Noofz”谢谢你的建议,让我先做一些基准测试......你以前用过这个,如果你用过,它在多线程环境中是如何工作的? cache.get(...) 操作每秒执行 5,000 到 30,000 次,并且可以达到两倍以上。
    • 不,可惜我没有在如此大的压力下使用它的经验。
    • 感谢您的参考。我有同样的要求——我一直在使用包装器对象来实现它,但是我需要减少一个非常大的映射占用的内存,而包装器对象是一个很大的开销。所以我想我的问题是 GNU Trove 地图实现是否节省空间。
    【解决方案2】:

    初始 Java API 将 equals / hashCode 行为限制为类型(类),因为当时他们没有 lambda。

    为了重用现有的 API/实现 - 制作临时密钥:

    public CountryKey {
        private String country;
        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof CountryKey)) { return false; }
            CountryKey that = (CountryKey) obj;
            return this.country.equals(that.country);
        }
        @Override int hashCode() {
             return country.hashCode();
        }
    }
    

    或包装器:

    public CountryKey {
        private GeoIpData holder;
        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof CountryKey)) { return false; }
            CountryKey that = (CountryKey) obj;
            return this.holder.getCountry().equals(that.holder.getCountry());
        }
        @Override int hashCode() {
             return holder.getCountry().hashCode();
        }
    }
    

    并为键编写辅助构造函数:

    public class GeoIpData {
         public CountryKey buildCountryKey() {
              return new CountryKey(this.country);
         }
    }
    

    【讨论】:

    • Trove 工作得很好——即使在我提到的更高负载下。然而,7 年多过去了,我同意你的观点,我会简单地创建密钥包装器。
    猜你喜欢
    • 1970-01-01
    • 2013-07-22
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2020-02-09
    • 1970-01-01
    相关资源
    最近更新 更多