2012-11-19 32 views
11

我有該結構的集合。我沒有重複,但當我打電話時: set.add(element) - >並且已經有確切的元素,我希望替換舊的元素。替換HashSet Java成員

import java.io.*; 

public class WordInfo implements Serializable { 
    File plik; 
    Integer wystapienia; 

    public WordInfo(File plik, Integer wystapienia) { 
     this.plik = plik; 
     this.wystapienia = wystapienia; 
    } 

    public String toString() { 
    // if (plik.getAbsolutePath().contains("src") && wystapienia != 0) 
      return plik.getAbsolutePath() + "\tWYSTAPIEN " + wystapienia; 
    // return ""; 
    } 
    @Override 
    public boolean equals(Object obj) { 
     if(this == obj) return true; 
     if(!(obj instanceof WordInfo)) return false; 
     return this.plik.equals(((WordInfo) obj).plik); 
    } 

    @Override 
    public int hashCode() {   
     return this.plik.hashCode(); 
    } 
} 
+0

無法理解的代碼片段和問題之間的關係。你能解釋一下,在代碼中設置它在哪裏?另外,如果你的物體完全一樣,那你爲什麼要更換? –

+0

@YogendraSingh - OP希望能夠用一個較新的'equals()'替換一箇舊的'WordInfo',但它不是同一個對象。 (注意,'equals()'測試忽略了'wystapienia'的值。) –

+0

@TedHopp:謝謝,但仍然是'return this.plik.equals(((WordInfo)obj).plik);'會讓它變成返回'true',否? –

回答

22

做一個刪除每個添加之前:

someSet.remove(myObject); 
someSet.add(myObject); 

刪除將刪除任何對象,等於爲myObject。或者,您可以查看加載結果:

if(!someSet.add(myObject)) { 
    someSet.remove(myObject); 
    someSet.add(myObject); 
} 

這將是更有效要看你怎麼經常有衝突。如果它們很少見,第二種形式通常只能做一次手術,但是當發生碰撞時它會做三次手術。第一種形式總是有兩種。

+0

這使我在線程中出現異常「main」java.util。ConcurrentModificationException'與Iterator一起使用時 – ThreaT

+0

@ThreaT這是一個與這個問題分開的問題,它是關於在可以調用'add'的情況下改變'add'的行爲。我建議把它作爲一個新問題,除了你可以發表評論的背景更多外,除非你能找到現有的問題來幫助你。 –

-1

檢查JDK中的HashSet代碼。 當元素被添加並且是重複的時,舊的值被替換。 民間認爲新元素被丟棄,這是錯誤的。 所以,你不需要額外的代碼。

更新---------------------

我重讀了在JDK的代碼,並承認錯誤,我已經做。

製作put時,VALUE被替換爲HashMap的KEY而不是KEY。

爲什麼我在談論Hashmap ?? !!因爲如果你看一下HashSet代碼,你會發現:

public boolean add(E e) { 
    return map.put(e, PRESENT)==null; 
} 

所以PRESENT值被替換爲新的一個如圖所示的代碼這一部分:

 public V put(K key, V value) { 
     if (key == null) 
      return putForNullKey(value); 
     int hash = hash(key); 
     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; 
    } 

但我同意,在key沒有被替換,並且由於key代表HashSet's的值,所以這個值被認爲是「未觸及的」。

+1

這是一個內部實現細節,應該不會被依賴。 – Perception

+0

但老留下;/ – Yoda

+0

如果發生替換,那麼HashSet不會跟隨用於添加的集合合:「該調用離開集合不變並返回false」 –

0

試試如下(這樣只會讓有道理的,如果equalshashCode依賴於一個領域,但在其他領域可以有不同的值):

if(!set.add(obj)) { 
    //set already contains the element (not the same object though) 
    set.remove(obj); //remove the one in the set 
    set.add(obj); //add the new one 
} 

退房的Set.add方法

的文檔

如果這個集合已經包含該元素,那麼該調用將保持該集合不變並返回false。

+0

-1這將無法正常工作。你總是想添加,不管'set()'返回什麼 – Bohemian

+0

我誤解了這個問題,改了它。 –

+0

確定沒有-1,但現在你的答案和Patricia的答案一樣,她首先回答「正確」 – Bohemian

3

如果該集合已經包含您試圖添加的元素equals()的元素,則新元素將不會被添加,並且不會替換現有元素。爲了保證新元素添加,只需從該組第一將其刪除:

set.remove(aWordInfo); 
set.add(aWordInfo); 
+0

就像一分鐘前那樣:)工作 – Yoda

0

我工作的地方我有一個組,然後我就想換成/從另一個對象覆蓋某些對象的問題組。

在我的情況下,我最終做的是創建一個新的集合,並在第一個覆蓋,然後添加當前對象第二。這是有效的,因爲在添加新對象時,集合不會替換任何現有的對象。

如果您有:

Set<WordInfo> currentInfo; 
Set<WorldInfo> overrides; 

相反的:

for each override, replace the object in current info 

我所做的:

Set<WordInfo> updated = new HashSet<>(); 
updated.addAll(overrides); 
updated.addAll(currentInfo);