简体   繁体   English

不向超级类列表添加任何重复项(检查子类是否相等)

[英]Add no duplicates to List of supperclass (check for equality with subclasses)

I have a List<Item> items = new ArrayList<>(); 我有一个List<Item> items = new ArrayList<>(); I add two different Items to, both subclasses of Item : PortableItem and SceneryItem . 我将两个不同的Item添加到Item两个子类: PortableItemSceneryItem

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

    ...

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

Now I would like to detect Items with duplicate ID s before adding a new one to my List. 现在,我想在将新ID添加到列表之前检测ID的项目。

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

Returns false. 返回false。 How can I change that behavior? 我该如何改变这种行为?

You could add an equals method that compared on id, be default an Object equals another when they are == - ie the same instance. 您可以添加一个与id进行比较的equals方法,默​​认情况下,当Object ==时, Object等于另一个-即同一实例。 This isn't what you want. 这不是你想要的。

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;
    }
}

This is really good practice anyway given your compareTo method and the requirement that is is consistent with equals - now a.equals(b) will return true if they have the same id . 无论如何,给定您的compareTo方法和与equals一致的要求,这确实是一个好习惯-现在a.equals(b)如果具有相同的id则将返回true。

As you now have an equals method you have to have a hashCode() method, again the consistent with equals requirement. 当您现在拥有一个equals方法时,您必须具有一个hashCode()方法,这也是与equals要求一致的方法。

Note that if you override the equals method in a superclass this obviously won't work unless you use a call to return super.equals at the end. 请注意,如果您在超类中覆盖equals方法,那么除非您使用调用最后return super.equals ,否则这显然将不起作用。

Now, using a List the contains method is guaranteed O(n) - this is very slow . 现在,使用List可以确保contains方法O(n)-这非常慢 I would recommend using a Set where contains is guaranteed O(1). 我建议使用一个contains保证为O(1)的Set If you need to maintain order use a LinkedHashSet or even better a TreeSet which will use your compareTo method to order items automagically. 如果您需要维护订单,请使用LinkedHashSet或更好的TreeSet ,它将使用您的compareTo方法自动订购商品。

You can always turn the thing into a List afterwards with one O(n) call anyway... 无论如何,您总是可以事后通过一个O(n)调用将其转换为List

You need to override the equals() and hashCode() methods in the base class to compare by ID. 您需要重写基类中的equals()hashCode()方法以按ID进行比较。
compareTo() is only used for sorting. compareTo()仅用于排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM