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
覆盖将fooObj
和fooObj2
视为“相等”,但是您的应用程序希望在某些地方将它们视为不同。这些冲突迟早会适得其反,会引入错误并给您带来头痛。我宁愿将标识符与数据分开,并给
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
标识。这可能与您当前的情况无关,但是如果您打算在将来的某个时间实现持久性,则可能希望已经开始在类层次结构中考虑此问题。