2011-01-04 5 views

Antwort

9

hier ein Fall unempfindliche Version eines ForwardingMap ist:

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

diese Karte verwenden, können Sie die MultiMap mit den Lieferanten Methoden in MultiMaps erstellen.

Beispiel:

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() wird nur Klein Werte zurück, unabhängig davon, wie die Tasten eingegeben wurden.

+3

Beachten Sie, dass es besser ist, String.toUpperCase anstelle von String.toLowerCase dafür zu verwenden, da einige Zeichen zwar im Großbuchstabenformat, aber nicht im Kleinbuchstabenformat mehreren Zeichen zugeordnet sind. Zum Beispiel wird das Zeichen '\ u00df' dem Großbuchstaben' \ u0053 \ u0053' zugeordnet, während '\ u0053 \ u0053' dem Kleinbuchstaben' \ u0073 \ u0073' zugeordnet wird. Aber offensichtlich wird '\ u00df' nicht als das selbe wie' \ u0073 \ u0073' betrachtet, während es semantisch ist. –

+0

@ Frór wow, wusste das nicht! Vielen Dank! –

1

Nein, aber vermutlich verwenden Sie String-Schlüssel? Wenn ja, warum nicht einfach alle Zugriffe auf eine reguläre Multimap normalisieren? Für den 80% -Fall wird das alle Anrufe setzen und den Schlüssel in Kleinbuchstaben setzen.

Für eine vollständige Diskussion über die Probleme mit der Groß- und Kleinschreibung multimaps finden this google group discussion

5

Könnten Sie nicht eine Map<String,List<Payload>> verwenden und es eine Comparator<String> geben, die Groß- und Kleinschreibung vergleichen tat?

Offenbar verfügen weder Google Collections noch Apache Collection Frameworks über eine Multimap, die einen Komparator zur Bewertung der Gleichheit der Schlüssel akzeptiert.

+3

Verwenden Sie [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) und liefert eine 'TreeMap' mit einem benutzerdefinierten Vergleicher –

+0

das Standard-Java equalsIgnoreCase ruft internLowerCase auf – sds

2

Sie könnten einen String-Komparator ohne Berücksichtigung der Groß-/Kleinschreibung mit einer Collator definieren. Erstellen Sie dann eine TreeMultimap mit Schlüsseln, die nach diesem Komparator sortiert sind.