简体   繁体   English

是否存在使用equals方法进行键检查的映射?

[英]Does a map using equals method for key checking exists?

I want to store data in a map, with key unicity, but I would like the map to use the equals method of my key class. 我想将数据存储在具有键唯一性的地图中,但我希望地图使用键类的equals方法。

It seems that HashMap doesn't use the equals method (I may be wrong, if so my tests are wrong). 似乎HashMap没有使用equals方法(我可能是错的,如果这样我的测试是错误的)。

My problem here is that the map use hashCode to check for duplicate, and I would like a map implementation that use equals. 我的问题是地图使用hashCode来检查重复项,而我想要一个使用equals的地图实现。

I am storing timestamp in the key, and would like to make it so that 2 keys are equals if there timestamp difference does not exceed a defined amount (let say 1000 ms). 我将时间戳存储在密钥中,并且如果时间戳差异不超过定义的数量(假设为1000毫秒),则希望使其等于2个密钥。

Edit : code 编辑:代码

public class CleanKey
{
    private DateTime start;
    private DateTime end;

    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((end == null) ? 0 : end.hashCode());
        result = prime * result + ((start == null) ? 0 : start.hashCode());
        return result;
    }

    public boolean equals(Object obj)
    {
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass())
            return false;
        CleanKey other = (CleanKey) obj;
        if(end == null)
        {
            if(other.end != null)
                return false;
        }
        else if(Math.abs(Millis.millisBetween(end, other.end).getMillis()) > 1000)
            return false;
        if(start == null)
        {
            if(other.start != null)
                return false;
        }
        else if(Math.abs(Millis.millisBetween(start, other.start).getMillis()) > 1000)
            return false;
        return true;
    }
}

It seems that HashMap doesn't use the equals method (I may be wrong, if so my tests are wrong). 似乎HashMap没有使用equals方法(我可能是错的,如果这样我的测试是错误的)。

It does use equals , but it uses hashCode first. 它确实使用equals ,但是首先使用hashCode It will only bother calling equals on keys with the same hash code - that's how it manages to be efficient. 它只会打扰在具有相同哈希码的键上调用equals这就是它设法提高效率的方式。 That's not a problem so long as your hashCode and equals method obey the contract specified in java.lang.Object . 只要您的hashCodeequals方法遵守java.lang.Object指定的约定,就没有问题。

I am storing timestamp in the key, and would like to make it so that 2 keys are equals if there timestamp difference does not exceed a defined amount (let say 1000 ms). 我将时间戳存储在密钥中,并且如果时间戳差异不超过定义的数量(假设为1000毫秒),则希望使其等于2个密钥。

You can't do that. 你不能那样做。 It violates the contract of equals, because you can't have transitivity. 它违反了平等合同,因为您不能具有传递性。 Suppose we have three keys x, y, and z with the following timestamps: 假设我们有三个带有以下时间戳记的键x,y和z:

x    400
y   1200
z   2000

By your description, x.equals(y) would be true, y.equals(z) would be true, but x.equals(z) would be false, thus violating the contract of Object.equals . 根据您的描述, x.equals(y)为true, y.equals(z)为true,但是x.equals(z)为false,从而违反了Object.equals的约定。

The equals method implements an equivalence relation on non-null object references: equals方法对非null对象引用实现对等关系:

  • It is reflexive : for any non-null reference value x, x.equals(x) should return true. 这是自反的 :对于任何非空参考值x,x.equals(x)应该返回true。
  • It is symmetric : for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. 它是对称的 :对于x和y的任何非空引用值,当且仅当y.equals(x)返回true时,x.equals(y)才返回true。
  • It is transitive : for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. 它是可传递的 :对于x,y和z的任何非空引用值,如果x.equals(y)返回true,而y.equals(z)返回true,则x.equals(z)应该返回true。
  • It is consistent : for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified. 它是一致的 :对于任何非空引用值x和y,只要未修改对象的equals比较中使用的信息,对x.equals(y)的多次调用将始终返回true或始终返回false。
  • For any non-null reference value x, x.equals(null) should return false. 对于任何非null参考值x,x.equals(null)应该返回false。

You need to override hashCode and equals in you class. 您需要在类中重写hashCode和equals。

Here: Understanding the workings of equals and hashCode in a HashMap 此处: 了解HashMap中equals和hashCode的工作原理

Edit after seeing the code : 看到代码后进行编辑:

Hashcode is returning wrong value because you are using end field to calculate the hash... different end lead to different hash. 哈希码返回错误的值,因为您正在使用end字段来计算哈希...不同的末端导致不同的哈希。

Just for a try... return a constant and the hashmap will work 只是尝试...返回一个常量,哈希表将起作用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM