2013-11-04 13 views
8

Ho notato (e apprezzato!) Che Guava di ImmutableMap.Builder non riesce a compilare se nel builder sono state aggiunte chiavi duplicate. Tuttavia, lo stesso comportamento (aggiunta di elementi duplicati) ha esito positivo con ImmutableSet.Perché ImmutableSet consente duplicati, ma ImmutableMap non è

C'è una ragione di questa differenza, e un buon modo per costruire un ImmutableSet con lo stesso comportamento fallimento?

Test case:

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

La mia ipotesi è che, i set sono progettati che si può inserire la stessa cosa due volte e hanno una sola copia di esso. Tuttavia con una mappa, se si mappa la stessa chiave con un nuovo valore, sovrascrive quello vecchio, e questo potrebbe non essere inteso comportamento – Cruncher

+0

Tuttavia, se il valore è lo stesso o no non ha rilevanza, fallisce velocemente su qualsiasi duplicato chiave. – dimo414

risposta

10

Sì, questo comportamento è intenzionale. Ecco un modo per pensarci: gli Set s vengono spesso creati da altri Collection s, in particolare da List, che potrebbero avere duplicati. Sarebbe molto imbarazzante - e inefficiente - richiedere agli utenti di scrivere ImmutableSet.copyOf(Sets.newHashSet(element)) se potrebbero esserci duplicati. D'altra parte, gli Map sono in genere costruiti da altri Map s, che non possono avere chiavi duplicate.

Se si vuole proibire gli elementi duplicati, la cosa migliore è qualcosa di simile

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

Questo ha senso, grazie! – dimo414

Problemi correlati