【问题标题】:HashSet adds two objects which returns true for equals() and has same hashcode in JavaHashSet 添加了两个对象,它们为 equals() 返回 true 并且在 Java 中具有相同的哈希码
【发布时间】:2021-08-12 14:18:11
【问题描述】:

frequencySet() 正在计算 Integer[]String 中每个字符的频率,该Counter 类具有覆盖的等号和哈希码。此方法应该只返回一个集合中唯一的频率,但同时添加了 Counter 对象。

从 print 语句可以看出:hashcode() 返回相等的值和equals() 返回true

怎么了?


class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // your code goes here
        String[] a = new String[2];
        a[0]="tan";
        a[1]="nat";
        Set<Counter>  s = frequencySet(a);
        System.out.println(s.size()); // prints
        System.out.println(getFreq(a[0]).equals(getFreq(a[1])) + ":" + getFreq(a[0]).hashcode() + ":" + getFreq(a[1]).hashcode() );
    }
public static Set<Counter> frequencySet(String[] strs) {
        Set<Counter> set =  new HashSet<>();
        for(String s: strs){
            Counter counter = getFreq(s);
            set.add(counter);
            //System.out.println(s + " : " + counter.hashcode() + " : " + Arrays.toString(counter.arr) );
        }
        return set;
    }
    
    private static  Counter getFreq(String s){
        Integer[] frequency = new Integer[26];
        for(char c : s.toCharArray()){
            Integer  a =  frequency[c-'a'];
            if(frequency[c-'a']==null){
                frequency[c-'a']=1;
            }
            else{
                a++;
                frequency[c-'a']=a; //++frequency[c-'a'];  
            }
        }
        //System
        return new Counter(frequency);
    }
}
    class Counter{
        Integer[] arr;
        public Counter(Integer[] arr){
            this.arr=arr;
        }
        
        public int hashcode(){
            //return Arrays.deepHashCode((Integer[])arr);
            int hashcode=31;
            for(int i=0;i<arr.length;i++){
                if(arr[i]==null)
                    hashcode+=i;
                else
                    hashcode+=31*arr[i];
            }
            return hashcode;
        }
        
        public boolean equals(Object o){
            //return Arrays.deepEquals(arr,(Integer[])o);
            Counter c = (Counter)o;
            Integer[] other = c.arr;
            for(int i=0;i<26;i++){
                if((arr[i]==null && other[i]!=null) || (arr[i]!=null && other[i]==null)){
                    return false;
                }
                else if(arr[i]!=null && other[i]!=null && arr[i]!=other[i]){
                    return false;
                }
            }
            return true;
        }
    }

输出:

    2
    true:417:417

&lt;script src="https://ideone.com/e.js/s2LcBw" type="text/javascript" &gt;&lt;/script&gt;

【问题讨论】:

    标签: java set equals hashset hashcode


    【解决方案1】:

    始终使用@Override。你已经实现了方法public int hashcode()。这不是你想的那样。你想要public int hashCode()。注意大写c。添加@Override 注释,编译器会出错(先尝试:@Override public int hashcode()...,然后编译它,注意错误,通过使hashCode 修复它。

    请注意,您的 hashCode impl 效率极低且很奇怪。你听说过一些关于素数的事情,但没有正确地实现它。正确的方法是在编写时将 哈希码 乘以一个素数(如果必须),而不是下一个元素值。

    更一般地说,Arrays.deepHashCode 在这里就可以了。我想这就是发生的事情:

    • 您使用 deepHashCode 编写了哈希码 impl。
    • 代码无效。
    • 您(错误地)指责 deepHashCode 是罪魁祸首,并编写了自己的哈希器。
    • 它仍然不起作用 - 合乎逻辑,因为这不是问题(用小写 c 编写哈希码是问题)。

    还原您的“修复” - 这段带有 deepHashCode 的代码更易于阅读且效率更高。

    【讨论】:

    • 是的。这就是发生的事情 - 你描述的场景。我写的 hashcode impl 只是一些幼稚的检查。谢谢。拼写错误会花费大量时间 :) 如果您必须节省一些时间,那么使用 @Override 是一个教训。
    【解决方案2】:

    您在hashcode() 中有错字,应该改为hashCode()。您可以通过添加 Override 注释来捕获此错误,在这种情况下编译器会通知您:

    @Override
    public int hashCode() {
    
    @Override
    public boolean equals(Object o) {
    

    【讨论】:

      猜你喜欢
      • 2014-08-11
      • 2013-04-30
      • 2012-07-31
      • 1970-01-01
      • 2011-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多