2013-03-14 50 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