0

我有一个List<Item> items = new ArrayList<>();我添加了两个不同的项目,两个子类ItemPortableItemSceneryItem

public class Item implements Comparable<item> {
    public String id;
    public String desc;

    ...

    public int compareTo(Item o) {
        return getId().compareTo(o.getId());
    }  
}

现在,我想ID在将新项目添加到我的列表之前检测具有重复 s 的项目。

    PortableItem a = new PortableItem("a");
    SceneryItem b  = new SceneryItem("a");
    items.add(a);
    items.contains(b); 

返回假。我怎样才能改变这种行为?

4

2 回答 2

4

您可以添加一个equals在 id 上进行比较的方法,默认情况下Object它们等于另一个==- 即相同的实例。这不是你想要的。

public class Item implements Comparable<Item> {

    public String id;
    public String desc;

    public String getId() {
        return id;
    }

    @Override
    public int compareTo(Item o) {
        return getId().compareTo(o.getId());
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 17 * hash + Objects.hashCode(this.id);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Item)) {
            return false;
        }
        final Item other = (Item) obj;
        if (!Objects.equals(this.id, other.id)) {
            return false;
        }
        return true;
    }
}

无论如何,鉴于您的方法和与 equals 一致compareTo的要求,这确实是一种很好的做法-如果它们具有相同的.现在将返回 true 。a.equals(b)id

因为你现在有一个equals方法,所以你必须有一个hashCode()方法,再次符合 equals 的要求。

请注意,如果您equals在超类中重写该方法,除非您在最后使用调用,否则这显然不起作用return super.equals

现在,使用Listcontains方法可以保证 O(n) - 这非常慢。我建议使用保证 O(1)的Set地方。contains如果您需要维护订单,请使用 aLinkedHashSet甚至更好的 a TreeSet,它将使用您的compareTo方法自动订购商品。

无论如何,您总是可以通过一个 O(n) 调用将事情变成List事后...

于 2013-03-14T18:51:32.407 回答
0

您需要覆盖基类中的equals()andhashCode()方法以按 ID 进行比较。
compareTo()仅用于排序。

于 2013-03-14T18:51:13.830 回答