2013-11-04 31 views
8

我注意到(並且讚賞!)番石榴的ImmutableMap.Builder無法建立,如果重複鍵已被添加到生成器。然而,同樣的行爲(添加重複的元素)成功與ImmutableSet爲什麼ImmutableSet允許重複,但ImmutableMap不會

是否有這種差異的原因,以及構建具有相同故障行爲的ImmutableSet的任何好方法?

測試用例:

import static org.testng.Assert.*; 
import org.testng.annotations.Test; 

import com.google.common.collect.ImmutableMap; 
import com.google.common.collect.ImmutableSet; 

public class ImmutableDuplicatesTest 
{ 
    @Test(expectedExceptions=IllegalArgumentException.class) // Note failure 
    public void mapDuplicates() { 
     ImmutableMap.Builder<String, String> map = ImmutableMap.builder(); 
     map.put("a", "a"); 
     map.put("b", "b"); 
     map.put("a", "c"); 
     assertEquals(map.build().size(), 2); 
    } 

    @Test // Passes normally 
    public void setDuplicates() { 
     ImmutableSet.Builder<String> set = ImmutableSet.builder(); 
     set.add("a"); 
     set.add("b"); 
     set.add("a"); 
     assertEquals(set.build().size(), 2); 
    } 
} 
+1

我的猜測是,集設計,你可以輸入同樣的事情兩次,只有它的一個副本。但是,使用映射時,如果將同一個鍵映射到新值,它將覆蓋舊值,並且這可能不是預期的行爲 – Cruncher

+0

但是,值是否相同無軸承,它會在任何重複鍵。 – dimo414

回答

10

是,這種行爲是經過深思熟慮的。這裏有一種思考方式:Set s經常從其他Collection s創建,尤其是List,它們可能有重複。如果可能存在重複,要求用戶編寫ImmutableSet.copyOf(Sets.newHashSet(element))會非常尷尬且效率低下。另一方面,Map通常由其他Map構建,其不能具有重複的密鑰。

如果你想禁止重複元素,你最好的選擇是一樣的東西

Set<E> set = new LinkedHashSet<E>(); 
for (E e : input) { 
    if (!set.add(e)) { 
    throw new IllegalArgumentException(); 
    } 
} 
return ImmutableSet.copyOf(set); 
+0

這很有道理,謝謝! – dimo414