如何从Collection返回一个对象。

时间:2013-06-07 19:17:56

标签: java list collections

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 ”,因此需要进行空检查,这也不好。

更新

使用getX()的关键值对来映射是一个好主意 - &gt; objFoo。如果我的Foo由两个字段定义,例如Foo类的X和Y,则 Map不能用于此目的。

2 个答案:

答案 0 :(得分:1)

您可以改为使用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@EmbeddedIdFooFooKey实体。这可能与您当前的场景无关,但如果您考虑将来某个时候实现持久性,您可能已经开始在类层次结构中考虑这一点。

答案 1 :(得分:0)

list.get(list.indexOf(fooObj))不是解决方法,而是List类的设计方式。如果您希望通过从List类继承,添加方法并使用新类型而不是{{}来可以 添加 get(Object) 1}}。但这似乎为这么小的好处做了很多工作。