2013-03-14 49 views
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); 

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

回答

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

这确实是很好的做法都会给出你compareTo方法,那就是要求一致等于 - 现在如果它们具有相同的ida.equals(b)将返回true。

正如你现在有一个equals方法,你必须有一个方法hashCode(),再次等于要求是一致的。

请注意,如果您在超类中重写equals方法,那么显然不起作用,除非最后使用对return super.equals的调用。

现在,使用List方法保证O(n) - 这是很慢。我会建议使用Set其中contains保证O(1)。如果您需要维护订单,请使用LinkedHashSet或更好的TreeSet,这将使用您的compareTo方法自动订购商品。

您可以随时打开的东西变成List后来与一个O(n)的调用反正...

+0

谢谢,这个工作。 – Sven 2013-03-14 18:58:02

0

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

+0

没有'的GetHashCode()','刚的hashCode()'。 – 2013-03-14 18:51:51

+0

@ bmorris591:固定;我太习惯C#了。 – SLaks 2013-03-14 18:52:19