class Foo
{
    int x;
    int y;
    int z;

    //Overriding equals() and hashCode() to just field x
}

List<Foo> myList=new ArrayList<Foo>();

myList.add(fooObj);
myList.add(fooObj2);


基本上,我的所有Foo对象都基于字段x进行比较。

我想根据值x从列表中获取fooObj。为什么添加诸如get(Object o)的方法而不是执行list.get(list.indexOf(fooObj))从列表中获取完整对象的方法是没有意义的。 indexOf()可以返回“ null”,因此需要进行null检查,这也不是很好。

更新:

拥有一个键值对getX()-> objFoo是一个好主意。如果我的Foo由两个字段(例如Foo类的X和Y)定义,则Map不能用于此目的。

最佳答案

您可以改用Map<Foo, Foo>

Map<Foo, Foo> map = new HashMap<Foo, Foo>();
// Store
map.put(fooObj, fooObj);
// Retrieve
map.get(fooObj2); // => fooObj


尽管我认为覆盖equals对于此用例不是一个很好的解决方案。您的equals覆盖将fooObjfooObj2视为“相等”,但是您的应用程序希望在某些地方将它们视为不同。这些冲突迟早会适得其反,会引入错误并给您带来头痛。

我宁愿将标识符与数据分开,并给Foo一个FooKey字段。

class FooKey {
    final int x;

    public FooKey(int x) {
        this.x = x;
    }

    // TODO Override equals and hashCode to only compare FooKeys on x field
}

class Foo {
    final FooKey id;
    int y;
    int z;

    public Foo(FooKey id) {
        this.id = id;
    }
}


这样,您的应用程序代码就变得更容易理解:

Map<FooKey, Foo> map = new ArrayList<FooKey, Foo>();
// Store
Foo fooObj = new Foo(new FooKey(123));
map.put(fooObj.id, fooObj);
// Retrieve
map.get(fooObj.id); // => fooObj
map.get(new FooKey(123)); // also fooObj if FooKey.equals is properly overridden


当您决定要在数据库中保留Foo对象时,使用单独的(复合)键字段也很有价值。例如,JPA允许您使用@IdClass@EmbeddedId允许Foo实体由FooKey标识。这可能与您当前的情况无关,但是如果您打算在将来的某个时间实现持久性,则可能希望已经开始在类层次结构中考虑此问题。

07-28 02:34