Ho bisogno di una mappa multipla con chiavi senza distinzione tra maiuscole e minuscole. esiste una tale implementazione nelle raccolte di google?c'è un multimap senza distinzione tra maiuscole e minuscole nelle raccolte google
risposta
Ecco una versione insensibile caso di un ForwardingMap
:
public class CaseInsensitiveForwardingMap<V> extends ForwardingMap<String, V>
implements Serializable{
private static final long serialVersionUID = -7741335486707072323L;
// default constructor
public CaseInsensitiveForwardingMap(){
this(new HashMap<String, V>());
}
// constructor with a supplied map
public CaseInsensitiveForwardingMap(final Map<String, V> inner){
this.inner = inner;
}
private final Map<String, V> inner;
@Override
protected Map<String, V> delegate(){
return inner;
}
// convert keys to lower case Strings, preserve null keys
private static String lower(final Object key){
return key == null ? null : key.toString().toLowerCase();
}
@Override
public V get(final Object key){ return inner.get(lower(key)); }
@Override
public void putAll(final Map<? extends String, ? extends V> map){
if(map == null || map.isEmpty()){ inner.putAll(map); }
else{
for(final Entry<? extends String, ? extends V> entry :
map.entrySet()){
inner.put(lower(entry.getKey()), entry.getValue());
}
}
}
@Override
public V remove(final Object object){ return inner.remove(lower(object)); }
@Override
public boolean containsKey(final Object key){
return inner.containsKey(lower(key));
}
@Override
public V put(final String key, final V value){
return inner.put(lower(key), value);
}
}
Utilizzando questa mappa, è possibile creare il MultiMap
utilizzando i metodi del fornitore in MultiMaps
.
Esempio:
Map<String, Collection<String>> map =
new CaseInsensitiveForwardingMap<Collection<String>>();
Multimap<String, String> caseInsensitiveMultiMap =
Multimaps.newMultimap(map, new Supplier<Collection<String>>(){
@Override
public Collection<String> get(){ return Sets.newHashSet(); }
});
Caveat: keySet()
torneranno valori minuscole solo, indipendentemente da quanto sono stati inseriti i tasti.
Si noti che è meglio utilizzare String.toUpperCase anziché String.toLowerCase per questo, poiché alcuni caratteri vengono associati a più caratteri pur essendo in maiuscolo, ma non mentre sono in minuscolo. Ad esempio, il carattere '\ u00df' è mappato al maiuscolo' \ u0053 \ u0053', mentre '\ u0053 \ u0053' è mappato al' \ u0073 \ u0073' minuscolo. Ma ovviamente '\ u00df' non è considerato lo stesso di \ u0073 \ u0073' mentre semanticamente lo è. –
@ Frór wow, non lo sapevo! Grazie! –
No, ma presumibilmente si stanno utilizzando le chiavi stringa? In tal caso, perché non normalizzare solo l'accesso a un multimap regolare? Per il caso dell'80%, ciò farà mettere tutte le chiamate e ottenere la chiave in minuscolo.
Per una descrizione completa dei problemi con multimaps case-insensitive, vedere this google group discussion
Non potresti usare un Map<String,List<Payload>>
e dare un Comparator<String>
, che ha fatto un case-insensitive confronto?
Sembra che né le raccolte di Google né i framework di Apache Collection dispongano di una multimap che accetta un comparatore per la valutazione dell'eguaglianza delle chiavi.
Utilizzare [MultiMaps.newListMultiMap()] (http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/ google/common/collect/Multimaps.html # newListMultimap% 28java.util.Map% 2C% 20com.google.common.base.Supplier% 29) e fornire una 'TreeMap' con un comparatore personalizzato –
le chiamate standard java equalsIgnoreCase aLowerCase internamente – sds
È possibile definire un comparatore di stringhe senza distinzione tra maiuscole e minuscole utilizzando un Collator. Quindi creare un TreeMultimap con le chiavi ordinate da quel comparatore.
raccolte Google è deprecato, aggiungendo tag guava, in quanto è il successore delle raccolte di google –