2014-04-01 81 views
0

現狀:防止重複而增加設置

讓我們假設我有一個這樣的類:

class Person { 
    public String name; 
    public String surname; 
    public age; 
} 

現在我要創建一組包含的一些基礎上某些人先前創建的列表(包含一些重複項)。當然,當我創建集合時,我不想在裏面有任何重複。

HashSet<Person> mySet = new LinkedHashSet<Person>(listOfPeople); 

問題: 讓我們假設,在某些情況下,「沒有重複」意味着我「的人以不同的名稱」。在其他情況下「的人不同年齡」

我看到HashSetadd方法使用putHashMap

public V put(K key, V value) { 
     if (key == null) 
      return putForNullKey(value); 
     int hash = hash(key.hashCode()); 
     int i = indexFor(hash, table.length); 
     for (Entry<K,V> e = table[i]; e != null; e = e.next) { 
      Object k; 
      if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // <== !! 
       V oldValue = e.value; 
       e.value = value; 
       e.recordAccess(this); 
       return oldValue; 
      } 
     } 
     modCount++; 
     addEntry(hash, key, value, i); 
     return null; 
    } 

問: 所以,我明白我應該只需覆蓋equals,Person並記得根據我的要求返回相同的hashCode對象應該「相等」。但是如果我的「平等」術語在運行時發生變化呢?

我在問,因爲在使用Collections.sort對一個集合進行排序時,我可以指定一個自定義Comparator,這使得我可以根據具體情況提供比較邏輯。

是否有任何類比機制,或者您知道的解決方案,它使我能夠在運行時決定在創建一組元素時組件是否相等?

我現在唯一的解決方案是在Person類中定義一些靜態Comparator,然後用這個比較器的方式重寫equals方法。然後,通過替換一個比較人,我實際上正在改變等於邏輯......它有道理嗎?

回答

1

我現在唯一的解決辦法是定義在Person類一些靜態的比較,然後重寫的equals方法以那種方式,它使用這個比較

不要那樣做。 Comparator合同中沒有任何內容要求將與.equals()不同的兩個對象與非零對象進行比較。可以放置的唯一限制是如果兩個對象是.equals()然後將它們相互比較,則它們給出0.然後將Comparable的實現稱爲「與等於」兼容。但是有些類甚至不尊重JDK中的類(參見BigDecimal)。

你有兩個選擇:

  • 使用SortedSet。 A TreeSet例如允許您在運行時通過Comparator。A SortedSet評估等同於兩個相互比較的實例給出0的事實,而不管.equals()
  • 如果您使用番石榴,您可以爲您的物體創建一個或多個Equivalence;您的Set將不得不擁有Equivalence.Wrapper<Person>類型的成員,而不僅僅是Person,您將不得不.add(eq.wrap(person)),但它的工作原理。
+0

是的,「包裝」關鍵字也在我心中!我認爲是非常複雜。但可能不會。感謝您的提示! –

0

您可以使用TreeSet<Person>用自己的比較

0

必須修改了一下你的Person類,並使用該定製的HashSet

public class CustomHashSet extends HashSet {   
    @Override 
    public boolean add(Object e) { 
     boolean flag = true; 
     Iterator<Object> itr = this.iterator(); 
     while(itr.hasNext()){ 
      if(itr.next().hashCode()==(e.hashCode())){ 
       flag = false; 
       break; 
      } 
     } 
     if(flag) 
      flag = flag & super.add(e); 
     return flag; 
    } 

} 

修改在人類

public class Person { 

    public String name; 
    public String surname; 
    public int age; 


    @Override 
    public boolean equals(Object obj) { 
     return (this == obj); 
    } 

    @Override 
    public int hashCode() { 
      int result = name.hashCode(); 
      result = 31 * result + age; 
      return result; 
    } 
} 

使用您自己的邏輯int散列碼方法重複檢查。

測試

public class TestB { 

public static void main(String[] args) { 
    HashSet a = new CustomHashSet(); 
    Person p = new Person("test","test1",1); 
    Person p1 = new Person("test","test1",1); 
    a.add(p); 
    a.add(p1); 
    System.out.println(a); 
} 

} 這將增加不允許只有一個元素重複的元素。希望這對你有幫助。 U也可以使用可比的接口實現。