【问题标题】:contains() method in java.util.HashSet doesn't behave as i expected from itjava.util.HashSet 中的 contains() 方法的行为不符合我的预期
【发布时间】:2011-08-09 05:55:54
【问题描述】:

这是 java main() 方法:



    public static void main(String[] args) {
        
        HashSet set = new HashSet();
        Mapper test = new Mapper("asd", 0);
        set.add(test);
        
        System.out.println(new Mapper("asd", 0).equals(test));
        System.out.println(set.contains(new Mapper("asd", 0)));
        
    }

我的 Mapper 类是:

class Mapper {

String word;
Integer counter;

Mapper (String word, Integer counter) {
    
    this.word = word;
    this.counter = counter;
    
}

public boolean equals(Object o) {
    
    if ((o instanceof Mapper) && (((Mapper)o).word == this.word)) {
        
        return true;
        
    }
    
    return false;
    
}

}

结果是:

是的

根据 HashSet 规范,在这个方法中我读到:“如果这个集合包含指定的元素,则返回 true。更正式地说,当且仅当这个集合包含一个元素 e 时才返回 true (o==null ? e= =null : o.equals(e))。"

那么,谁能解释我哪里错了?还是……?

谢谢。

【问题讨论】:

  • 只是为了添加一些东西,如果你想比较它的值,你应该使用 String equals() 方法(而不是 ==,这是参考测试)。

标签: java hashset


【解决方案1】:

你需要实现一个合适的hashCode()函数。

public int hashCode() {
  // equal items should return the same hashcode
}

Java 实用程序java.util 包含许多依赖散列的类。允许一个人在他们认为合适的时候覆盖equals(),这意味着一个人还必须正确地覆盖hashCode()才能匹配。

hashCode() 的正确实现将为 equals() 返回 true 的任何两个对象返回相同的哈希值。哈希相关函数在检查对象是否相等(以解决哈希冲突)之前检查哈希是否相等。

【讨论】:

  • ... 当您使用它时,请更正(或清楚地记录)您的 equals 以不使用字符串的引用相等。在这种情况下,您可以侥幸逃脱,因为“asd”在同一个类文件中被使用了两次。但是,例如,如果您从用户输入中读取了字符串,那么第一次比较也会失败。
  • @Dilum:为什么呢?我知道字符串是在初始化 JVM 时分开创建的字符串内存池中创建的。
  • @artaxerxe 字符串是对象。 hashCode() 的默认实现是为每个实例返回一个唯一的数字。如果您创建两个字符串ala a1 = new String("a"); a2 = new String("a"); 可能会期望a1 == a2false,因为它们不是同一个对象(由于两个新调用)。这意味着对于字符串(和其他对象)a1.equals(a2) 通常要安全得多。
  • @artaxerxe 您所说的仅适用于明确实习的字符串。 (download.oracle.com/javase/1.4.2/docs/api/java/lang/…)。假设您阅读了一个 XML 文档,并且您获得了一个包含“asd”和“0”属性的元素。这些不是实习字符串。这是字符串没有被保留的无数案例之一。试试这个来说明我的观点: System.out.println(new Mapper("asd".toUpperCase().toLowerCase(), 0).equals(test));
【解决方案2】:

hashCode contract 表示如果两个对象相等,它们应该具有相同的哈希码。像HashSet 这样的集合假定这是支持的。

ObjectequalshashCode 实现基于地址(或对象 ID)。如果您覆盖 equals 进行内容比较,则应覆盖 hashCode 以根据内容生成哈希。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-15
    • 2013-10-18
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 2022-01-06
    • 1970-01-01
    相关资源
    最近更新 更多