Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 首选的Equals()方法实现_Java - Fatal编程技术网

Java 首选的Equals()方法实现

Java 首选的Equals()方法实现,java,Java,这是一个关于如何实现equals方法的问题,当我需要在给定一个值的列表中查找对象的实例时,我的一个实例在其成员中有一个值 我有一个对象,其中我实现了equals: class User { private String id; public User(id) { this.id = id; } public boolean equals(Object obj) { if (!(obj instanceof User)) {

这是一个关于如何实现equals方法的问题,当我需要在给定一个值的列表中查找对象的实例时,我的一个实例在其成员中有一个值

我有一个对象,其中我实现了equals:

class User {

    private String id;

    public User(id) {
        this.id = id;
    }

    public boolean equals(Object obj) {
        if (!(obj instanceof User)) {
            return false;
        }
        return ((User)obj).id.equals(this.id);
    }
}
现在,如果我想在列表中找到一些东西,我会这样做:

public function userExists(String id) {
        List<Users> users = getAllUsers(); 
        return users.contains(new User(id));
}
换言之:

public function userExists(String id) {
    List<Users> users = getAllUsers(); 
    return users.contains(id);
}
公共函数userExists(字符串id){
列表用户=getAllUsers();
返回users.contains(id);
}

第二种方法是危险的,因为它破坏了等式的对称性


Java希望
equals()
的实现是自反的、对称的和可传递的。第二个实现打破了对称性:如果将
用户
与表示其ID的
字符串
进行比较,则会得到
,但如果将该字符串与用户进行比较,则首先会得到
,第二个实现在功能上等同于第一个实现,因为
String
的实例不是
User
的实例,第一个
return
语句将在检查
字符串之前将其短路

我的意思是

public boolean equals(Object obj) {
    if (!(obj instanceof User)) { // This will execute if obj is a String
        return false;
    }
    if (obj instanceof String) {
        // Never executes, because if obj is a String, we already
        // returned false above
        return ((String)obj).equals(this.id);
    }
    return ((User)obj).id.equals(this.id);
}
因此,对于答案的其余部分,我将假设所指的是

public boolean equals(Object obj) {
    if ( obj == null ) return false; // Add a null check for good measure.
    if (!(obj instanceof User)) {
        if (obj instanceof String) {
            // Now we're checking for a String only if it isn't a User.
            return ((String)obj).equals(this.id);
        }
        return false;
    }
    return ((User)obj).id.equals(this.id);
}
现在我们来谈谈实际问题


用户
返回
到-
字符串
比较的
等于
是不好的做法,因为
等于
应该是对称的(
a.equals(b)
当且仅当
b.equals(a)
)。由于
字符串
永远不可能等于
用户
,因此
用户
永远不应该等于
字符串

对于数学上不相等的事物,不要覆盖equals

你可能认为这是一个好主意

User bob = new User("Bob");
if (bob.equals("Bob")) {
  ...
}
但事实很少如此。当
字符串
用户
相等时,是否希望所有观察代码的相等者都感到困惑

如果需要查找方法,请编写它

class User {

    private String id;

    public boolean equals(Object obj) {
        if (obj instanceof User) {
            User other = (User)obj;
            if (id.equals(other.id)) {
              return true;
            }
        }
        return false;
    }

    public String getId() {
        return id;
    }

}
然后将代码放在别处以维护“快速查找”表


第二选择很糟糕。这意味着您允许用户将
user
以外的内容传递给
user.equals()
(即,当您不是真正尝试与用户比较字符串时,实际上是
Object.equals()
),因此您实际上违反了
equals
应该做的事情的约定


另外,两个答案都不处理空检查。

如果覆盖Object.equals(),请不要忘记覆盖Object.hashCode()


相等的对象必须具有相等的哈希代码,如果不遵守约定,您可能会在集合中遇到问题。

实际上,我遇到了一堆代码,它们具有“相等”的idom与所有错误步骤一样,一开始并不太糟糕,但随着
集合
开始被大量使用,大量的变通代码被打包在一起,我认为第二种技术是一个bug而不是一个好处。我记得在Sierra/Bates中读到过关于对称的内容,但我想当时我只是浏览了一下。现在我知道得更多。但是,是吗创建虚拟用户对象以在列表中查找用户,给定ID作为字符串,是否正确?@udeleng否,创建虚拟用户以在列表中查找
用户
。使用
迭代器
搜索列表,检查每个元素上的字段,或者将用户存储在按ID索引的
映射中(如下例所示)
user.equals(Object)的正确实现
在列表中搜索之前,需要您已经找到了所需的用户。谢谢,我发现了我在短路方面的错误。我只是在发布时在这里键入了代码。我现在了解了对称原则。请看一下我回答@dasblinkenlight的问题。@trutheality老实说,我完全没有领会您的意思。我抱歉,我的假设是他写的第二个equals实现是半正确的,而不是一个概念错误上的错误实际上可以挽救这一天。我想我最好放慢阅读速度,或者喝杯咖啡。我大体上同意你的答案,但OP是覆盖而不是超载的
class User {

    private String id;

    public boolean equals(Object obj) {
        if (obj instanceof User) {
            User other = (User)obj;
            if (id.equals(other.id)) {
              return true;
            }
        }
        return false;
    }

    public String getId() {
        return id;
    }

}
Map<String, User> idTable = new HashMap<String, User>();
User bob = new User("Bob");
idTable.put(bob.getId(), bob);

public User findUser(String id) {
  return idTable.get(id);
}
List<User> users = new List<User>();
users.add(new User("Bob"));
users.add(new User("Steve"));
users.ass(new User("Ann"));

public User findUser(String id) {
  Iterator<User> index = users.iterator();
  while (index.hasNext()) {
    User user = index.next();
    if (id.equals(user.getId())) {
      return user;
    }
  }
  return null;
}