2011-01-04 4 views

Respuesta

9

Aquí es una versión insensible caso de 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); 
    } 
} 

El uso de este mapa, puede crear el MultiMap utilizando los métodos de proveedores MultiMaps.

Ejemplo:

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(); } 

    }); 

Advertencia: keySet() sólo devolverá los valores en minúsculas, independientemente de cómo se introdujeron las llaves.

+3

Tenga en cuenta que es mejor usar String.toUpperCase en lugar de String.toLowerCase para esto, ya que algunos caracteres se asignan a varios caracteres mientras están en mayúscula, pero no mientras están en minúscula. Por ejemplo, el caracter '\ u00df' está mapeado en mayúscula' \ u0053 \ u0053', mientras que '\ u0053 \ u0053' está mapeado en minúscula' \ u0073 \ u0073'. Pero obviamente '\ u00df' no se considera lo mismo que' \ u0073 \ u0073' mientras que semánticamente sí lo es. –

+0

@ Frór wow, ¡no lo sabía! ¡Gracias! –

1

No, pero presumiblemente está utilizando las teclas de cadena? Si es así, ¿por qué no simplemente normalizar todos los accesos a un multimap regular? Para el caso del 80%, eso hará que todas las llamadas se pongan y se ponga la tecla en minúscula.

Para una discusión completa de los problemas con Multimapas mayúsculas y minúsculas, ver this google group discussion

5

No se pudo utilizar una Map<String,List<Payload>> y darle un Comparator<String> que hizo un sensible a las mayúsculas comparar?

Parece que ni Google Collections ni los marcos de la Colección Apache tienen un multimapa que acepta un Comparador para evaluar la igualdad de claves.

+3

Utilice [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) y proporciona un 'TreeMap' con un comparador personalizado –

+0

el estándar java es igual aIgnoreCase llama a LowCase internamente – sds

2

Puede definir un Comparador de Cadenas insensible a mayúsculas y minúsculas usando un Collator. Luego crea un TreeMultimap con claves ordenadas por ese Comparador.

Cuestiones relacionadas