4

这个问题的答案可能是“不可能的”,但无论如何让我问一下:)

假设我们有一个非常简单的 JAVA 类,它有一个主键,例如:

class Person {
    String ssid;
    String name;
    String address;
    ...
}

现在,我想将人员存储在一个集合中,这意味着我必须重写 equals 方法。不是一件完全微不足道的事情,但在一个简单的基础上,我会有一些类似的东西:

@Override
public boolean equals (Object other) {
    if(other==this) return true;
    if(!other.getClass().equals(this.getClass()) return false;
    Person otherPerson = (Person)other;
    if(this.ssid.equals(otherPerson.getSsid()) return true;
}

原谅任何明显的错误,只是从我的脑海中输入这个。现在,让我们稍后在应用程序中说,我有一个通过用户输入获得的 ssid。如果我想将我的 ssid 与一个人进行比较,我将不得不调用类似:

String mySsid = getFromSomewhere();
Person myPerson = getFromSomewhere();
if(myPerson.equals(new Person(mySsid)) doSomething();

这意味着我必须创建一个方便的构造函数来创建一个基于 ssid 的 Person(如果我还没有的话),而且它也很冗长。简单地打电话会更好

myPerson.equals(mySsid)

但是如果我向我的 Person equals 类添加了一个字符串比较,那会破坏对称属性,因为 String 不知道如何将自己与 Person 进行比较。

所以最后,最大的问题是,有没有办法使用覆盖的 equals 方法启用这种“速记”比较,而不破坏对称规则?

感谢您对此的任何想法!

编辑:澄清一下,这更像是一个悬而未决的问题,而不是寻求确切解决方案的问题。当我想从集合中提取一个 Person 时,equals 应该满足这种情况。所以应该可以做这样的事情:

List<Person> people = ...
people.get(ssid);

能够基于主键在类上定义相等性似乎是显而易见且直观的,但我还没有找到一种直接的方法来做到这一点。

4

6 回答 6

3

更好的选择是将您的人员存储在地图中,然后您可以轻松地检索它们:

HashMap<String, Person> people = new HashMap<String, Person>();

Person p = constructPersonFromStuff();

people.put(p.ssid, p);

然后稍后,您可以查看该人是否存在:

String ssid = getFromSomewhere();

if(people.contains(ssid)){
  Person thatGuy = people.get(ssid);
}else{
  //that person DOESN'T EXIST! HE'S A FIGMENT OF YOUR IMGAINATION!
}
于 2010-05-04T16:01:36.513 回答
2

您不是在比较两个Persons,而是在比较两个ssids。我会使用:

myPerson.getSsid().equals(mySsid);
于 2010-05-04T16:01:05.933 回答
1

说 aPerson等于字符串是没有意义的,不要走那条路。

我只是不明白你的问题。你有这个代码:

String mySsid = getFromSomewhere();
Person myPerson = getFromSomewhere();
if (myPerson.getSsid().equals(mySsid) doSomething();

这对我来说并不坏。我想你可以定义一个函数来为你做这件事:

if (myPerson.ssidEquals(mySsid)) doSomething();

但这真的不是很大的进步。

有什么问题?

于 2010-05-04T16:01:54.043 回答
1

我认为 Person 不等于 ssid。您使用 ssid 比较来确定两个 Person 是否相等这一事实是一种捷径——我们接受具有相同 ssid 的两个 Person 指代同一现实世界的人作为约定——但实际上并不是导致相等的原因真的。

也许您在这里真正想要的是给您的 Person 一个布尔“hasSsid()”方法。或者只是打电话myPerson.getSsid().equals(mySsid)

于 2010-05-04T16:02:03.873 回答
0

当 equals 方法的参数不是调用该方法的类的实例时,equals 方法绝不能返回 true。

如果你愿意,你可以创建一个接口,比如 Identifiable。

public interface Identifiable {
    public Serializable getSsid();
}

public class Person implements Identifiable { ...

然后,您可以根据 Identifiable 以通用方式编写代码……这可能会有所帮助。

(我假设真正的问题是以通用方式处理您的可识别对象以用于实用程序等)。

于 2010-05-04T16:06:36.797 回答
0

您可以创建一个使用地图或在内部设置的自定义数据结构:

public interface EntityStore<T,K> {
    T get(K id);
    boolean contains(Object o);
    void put(K id, T entity);
    void remove(Object o);
    // ...
}

public class MapEntityStore<T,K> {
    private Map<K,T> entities = new HashMap<K,T>();
    public T get(K id) { return entities.get(id); }
    public boolean contains(Object o) {
        if (entities.keySet().contains(o))
            return true; // search by id
        if(entities.values().contains(o))
            return true; // search by value (this can be optimized if necessary)

        return false;
    }
    ...
}

您可以使用工厂方法来创建 EntityStore 的实例,以便您可以根据需要更改为优化/花哨的实现。

于 2010-05-04T16:17:51.857 回答