HashMap anahtarı olarak büyük / küçük harfe duyarlı olmayan dize


178

Aşağıdaki nedenlerden dolayı bir HashMap anahtarı olarak büyük / küçük harfe duyarlı olmayan dize kullanmak istiyorum.

  • Başlatma sırasında, programım kullanıcı tanımlı Dize ile HashMap oluşturur
  • Bir olayı işlerken (benim durumumda ağ trafiği), farklı bir durumda String alabilirim, ancak <key, value> trafikten aldığım durumu görmezden gelip HashMap'ten .

Bu yaklaşımı izledim

CaseInsensitiveString.java

    public final class CaseInsensitiveString {
            private String s;

            public CaseInsensitiveString(String s) {
                            if (s == null)
                            throw new NullPointerException();
                            this.s = s;
            }

            public boolean equals(Object o) {
                            return o instanceof CaseInsensitiveString &&
                            ((CaseInsensitiveString)o).s.equalsIgnoreCase(s);
            }

            private volatile int hashCode = 0;

            public int hashCode() {
                            if (hashCode == 0)
                            hashCode = s.toUpperCase().hashCode();

                            return hashCode;
            }

            public String toString() {
                            return s;
            }
    }

LookupCode.java

    node = nodeMap.get(new CaseInsensitiveString(stringFromEvent.toString()));

Bu nedenle, her olay için yeni bir CaseInsensitiveString nesnesi oluşturuyorum. Yani, performansı etkileyebilir.

Bu sorunu çözmenin başka bir yolu var mı?


3
[Harita <Dize,?> Almak ve görmezden gelmek için iyi bir yol var mı?] [1] [1]: stackoverflow.com/questions/212562/…
Beau Grantham

Aşağıdaki konular hakkında yorum yaptım, ancak eşik değerin altında, bu yüzden insanlar onları görmeyebilir. HashMap alt sınıflarına dikkat edin. JDK8 uygulamayı değiştirdi ve şimdi bu önerilerin çalışması için putAll'ı (en azından) geçersiz kılmanız gerekiyor.
Steve N

Bu iyi olmalı. Yeni nesne örneklemesinden kurtulmak için bir sinek ağırlığı kullanabilirsiniz.
topkara

Yanıtlar:


331
Map<String, String> nodeMap = 
    new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

Gerçekten ihtiyacın olan bu.


6
Bu, şimdiye kadarki en basit olanıdır ve aynı zamanda anahtarlar arasında yineleme yaparken de durumu korur.
Ralf

Bu güzel! Bu, ColdFusion'da nokta gösterimini kullanma yeteneğini koruyan sıralı bir yapı oluşturma bulmacasının son parçasıydı. Var struct = {} veya var struct = structnew () yerine var struct = createObject ('java', 'java.util.TreeMap') yerine init (createObject ('java', 'java.lang.String') ) .CASE_INSENSITIVE_ORDER); FUGLY, ama işe yarar;)
Eric Fuller

public static <K extends String, V> Map<K, V> caseInsensitiveMap() { return new TreeMap<K, V>(String.CASE_INSENSITIVE_ORDER); }
pllee

5
O <K extends String>zamandan beri gerek yok String: public static <V> Map<String, V> caseInsensitiveMap() { return new TreeMap<String, V>(String.CASE_INSENSITIVE_ORDER); }
Roel Spilker

19
TreeMap'in temel işlemler için sabit bir süre olmadığını unutmayın. Çoğu uygulama için bir sorun değil, akılda tutmaya değer. JavaDoc'dan: "Bu uygulama, içerenKey, alma, koyma ve kaldırma işlemleri için garantili günlük (n) zaman maliyeti sağlar. Algoritmalar Cormen, Leiserson ve Rivest'in Algoritmalara Giriş'lerinin uyarlamalarıdır."
James Schek

57

Guido García'nın buradaki cevabında önerdiği gibi :

import java.util.HashMap;

public class CaseInsensitiveMap extends HashMap<String, String> {

    @Override
    public String put(String key, String value) {
       return super.put(key.toLowerCase(), value);
    }

    // not @Override because that would require the key parameter to be of type Object
    public String get(String key) {
       return super.get(key.toLowerCase());
    }
}

Veya

https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/CaseInsensitiveMap.html


28
Nasıl içerir, putAll, vb?
assylias

14
Türkçe gibi bazı dillerde çalışmaz. Google "Türkiye testi"
Hugo

5
@assylias: doğru containsKey()ve remove()aynı şekilde geçersiz kılınmalıdır get(). HashMap.putAll()uygulama kullanır put(), bu yüzden bu bir problem olmamalı - sürece HashMap uygulama kalır aynıdır. ;) get()yöntem imzası Objectda a değil bağımsız değişken olarak alır String. kod ayrıca bir boş anahtarı test etmez:super.get(key == null ? null : key.toString().toLowercase());
sfera

kopya yapıcısına ihtiyacınız varsa HashMap(<? extends String, ? extends String> anotherMap), aynı kurucunun süper uygulamasını çağırmamalısınız, çünkü bu işlem anahtarlarınızın küçük harfli olacağını garanti etmez. kullanabilirsiniz: super(anotherMap.size()); putAll(anotherMap);bunun yerine.
sfera

Haritanın değerlerinin dize olmamasını isterseniz ne olur? (yani CaseInsensitiveMap<String, Integer>)
Adam Parkin

16

Bir yaklaşım Apache Commons özel bir alt sınıfını oluşturmak için AbstractHashedMapgeçersiz kılma, sınıf hashve isEqualKeysbüyük harf duyarsız hash ve tuşların karşılaştırma yapmak için yöntemler. (Not - Bunu kendim hiç denemedim ...)

Bu, her bir harita araması veya güncellemesi yapmanız gerektiğinde yeni nesneler oluşturma yükünü ortadan kaldırır. Ve ortak Mapoperasyonlar O (1) ... tıpkı normal gibi HashMap.

Ve yaptıkları uygulama seçimlerini kabul etmeye hazırsanız, Apache Commons CaseInsensitiveMapsizin için özelleştirme / uzmanlık işi yapar AbstractHashedMap.


Ancak O (logN) getve putişlemler kabul edilebilirse, büyük / TreeMapküçük harf duyarlı olmayan bir dize karşılaştırıcısı bir seçenektir; örneğin String.CASE_INSENSITIVE_ORDER.

Ve her yaptığınızda yeni bir geçici String nesnesi oluşturmanın sakıncası putyoksa get, o zaman Vishal'in cevabı gayet iyi. (Yine de, eğer bunu yaparsanız anahtarların orijinal durumunu korumazsınız ...)


6

Alt sınıfı HashMaptıklatın putve anahtarı ve get(ve muhtemelen diğer anahtar yönelimli yöntemleri) küçük harfe çeviren bir sürümü oluşturun .

Ya da a'yı HashMapyeni sınıfa birleştirin ve her şeyi haritaya devredin, ancak anahtarları çevirin.

Orijinal anahtarı saklamanız gerekiyorsa, ikili haritaları koruyabilir veya orijinal anahtarı değerle birlikte saklayabilirsiniz.


Arama sırasında bir String.toLowerCase () yapmak mı demek istediniz?
rs

@ Değil user710178 sadece arama sırasında, ama depolama sırasında da.
Dave Newton

@ user710178 Oh, doğru, diğer yanıtın da işaret ettiği gibi, ek bir bağımlılık sakıncası yoksa bu zaten var.
Dave Newton

@StephenC İhtiyaçlarınızı karşılıyorsa, kesinlikle; OP bir belirledi HashMap, işte ben de öyle gittim :) Ah, Commons demek istedim; Anlıyorum. Sanırım, ihtiyacınız olmadığı sürece üretildi (ya da nihayetinde jenerikler var mı?)
Dave Newton

1
JDK 8 ve üstü için, uygulama değiştikçe putAll'ı (en azından) geçersiz kılmanız gerekir.
Steve N

4

Aklıma iki seçenek geliyor:

  1. s.toUpperCase().hashCode();Anahtarını doğrudan kullanabilirsiniz Map.
  2. Davayı görmezden gelen TreeMap<String>bir özel ile bir kullanabilirsiniz Comparator.

Aksi takdirde, çözümünüzü tercih ederseniz, yeni bir Dize türü tanımlamak yerine, gerekli büyük / küçük harf duyarsızlığı işlevine sahip yeni bir Harita uygulamayı tercih ederim.


3

HashCode'u ezberlemek için Dizeyi "sarmak" daha iyi olmaz mıydı. Normal String sınıfında hashCode () ilk kez O (N) ve daha sonra kullanılmak üzere saklandığı için O (1) olur.

public class HashWrap {
    private final String value;
    private final int hash;

    public String get() {
        return value;
    }

    public HashWrap(String value) {
        this.value = value;
        String lc = value.toLowerCase();
        this.hash = lc.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o instanceof HashWrap) {
            HashWrap that = (HashWrap) o;
            return value.equalsIgnoreCase(that.value);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return this.hash;
    }

    //might want to implement compare too if you want to use with SortedMaps/Sets.
}

Bu, Java'da Hashtable'ın herhangi bir uygulamasını kullanmanıza ve O (1) hasCode () özelliğine sahip olmanızı sağlar.


3

Bir kullanabilirsiniz HashingStrategy esaslı Mapgelen Eclipse Koleksiyonları

HashingStrategy<String> hashingStrategy =
    HashingStrategies.fromFunction(String::toUpperCase);
MutableMap<String, String> node = HashingStrategyMaps.mutable.of(hashingStrategy);

Not: Eclipse Collections'a katkıda bulunuyorum.


2

Diğer cevaplara dayanarak, temel olarak iki yaklaşım vardır: alt sınıflandırma HashMapveya sarma String. İlki biraz daha çalışma gerektiriyor. Aslında, doğru bir şekilde yapmak istiyorsanız, neredeyse tüm yöntemleri ( containsKey, entrySet, get, put, putAll and remove) geçersiz kılmalısınız .

Her neyse, bir sorunu var. Gelecekteki sorunlardan kaçınmak istiyorsanız Locale, büyük / Stringküçük harfe yönelik işlemler belirtmeniz gerekir . Böylece yeni yöntemler yaratabilirsiniz ( get(String, Locale), ...). Her şey daha kolay ve daha net sarma Dize:

public final class CaseInsensitiveString {

    private final String s;

    public CaseInsensitiveString(String s, Locale locale) {
        this.s = s.toUpperCase(locale);
    }

    // equals, hashCode & toString, no need for memoizing hashCode
}

Performans konusundaki endişeleriniz hakkında: erken optimizasyon tüm kötülüklerin köküdür :)


2
"Ve iyi, performans endişeleriniz hakkında: erken optimizasyon tüm kötülüğün kökü :)" - Aksine, her zaman verimsiz kod yazmak için bir bahane olarak kullanmak şeytani şeydir.
Gordon

1
Aslında @ Gordon, bağlama bağlı olarak her ikisi de eşit derecede kötü. "Kötülük" etiketi, "en iyi uygulama" ve birçok BT insanının kullanma eğiliminde olduğu diğer çeşitli yararsız ifadeler gibi siyah beyaz düşünmenin bir işaretidir. Tamamen önlemek için en iyisi.
Stephen C

İnsanlara "en iyi uygulamayı" takip etmediklerini söylerken, kötü uygulamalara sahip olduklarını söylemekten daha az topuklu ayakkabı kazma eğilimi gösterdiğini gördüm.
Gordon

0

Bu, yeni bir proje için uyguladığım HashMaps için bir adaptör. @SandyR'nin yaptıklarına benzer şekilde çalışır, ancak dizeleri bir sarmalayıcı nesnesine manuel olarak dönüştürmemeniz için dönüştürme mantığını içerir.

Java 8 özelliklerini kullandım, ancak birkaç değişiklik yaparak önceki sürümlere uyarlayabilirsiniz. Yeni Java 8 akış işlevleri dışında en yaygın senaryolar için test ettim.

Temelde bir HashMap'i sarar, bir sarmalayıcı nesnesine / nesnesinden dizeleri dönüştürürken tüm işlevleri ona yönlendirir. Ancak KeySet ve EntrySet'i de uyarlamak zorunda kaldım çünkü bazı fonksiyonları haritanın kendisine iletiyorlardı. Bu nedenle, orijinal keySet () ve entrySet () 'i gerçekten saran anahtarlar ve girişler için iki yeni Set döndürürüm.

Bir not: Java 8, geçersiz kılmanın kolay bir yolunu bulamadığım putAll yönteminin uygulanmasını değiştirdi. Dolayısıyla, özellikle büyük bir veri kümesi için putAll () kullanırsanız, geçerli uygulama performansı düşmüş olabilir.

Bir hata bulursanız veya kodu iyileştirmek için önerileriniz varsa lütfen bize bildirin.

paket webbit.collections;

import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;


public class CaseInsensitiveMapAdapter<T> implements Map<String,T>
{
    private Map<CaseInsensitiveMapKey,T> map;
    private KeySet keySet;
    private EntrySet entrySet;


    public CaseInsensitiveMapAdapter()
    {
    }

    public CaseInsensitiveMapAdapter(Map<String, T> map)
    {
        this.map = getMapImplementation();
        this.putAll(map);
    }

    @Override
    public int size()
    {
        return getMap().size();
    }

    @Override
    public boolean isEmpty()
    {
        return getMap().isEmpty();
    }

    @Override
    public boolean containsKey(Object key)
    {
        return getMap().containsKey(lookupKey(key));
    }

    @Override
    public boolean containsValue(Object value)
    {
        return getMap().containsValue(value);
    }

    @Override
    public T get(Object key)
    {
        return getMap().get(lookupKey(key));
    }

    @Override
    public T put(String key, T value)
    {
        return getMap().put(lookupKey(key), value);
    }

    @Override
    public T remove(Object key)
    {
        return getMap().remove(lookupKey(key));
    }

    /***
     * I completely ignore Java 8 implementation and put one by one.This will be slower.
     */
    @Override
    public void putAll(Map<? extends String, ? extends T> m)
    {
        for (String key : m.keySet()) {
            getMap().put(lookupKey(key),m.get(key));
        }
    }

    @Override
    public void clear()
    {
        getMap().clear();
    }

    @Override
    public Set<String> keySet()
    {
        if (keySet == null)
            keySet = new KeySet(getMap().keySet());
        return keySet;
    }

    @Override
    public Collection<T> values()
    {
        return getMap().values();
    }

    @Override
    public Set<Entry<String, T>> entrySet()
    {
        if (entrySet == null)
            entrySet = new EntrySet(getMap().entrySet());
        return entrySet;
    }

    @Override
    public boolean equals(Object o)
    {
        return getMap().equals(o);
    }

    @Override
    public int hashCode()
    {
        return getMap().hashCode();
    }

    @Override
    public T getOrDefault(Object key, T defaultValue)
    {
        return getMap().getOrDefault(lookupKey(key), defaultValue);
    }

    @Override
    public void forEach(final BiConsumer<? super String, ? super T> action)
    {
        getMap().forEach(new BiConsumer<CaseInsensitiveMapKey, T>()
        {
            @Override
            public void accept(CaseInsensitiveMapKey lookupKey, T t)
            {
                action.accept(lookupKey.key,t);
            }
        });
    }

    @Override
    public void replaceAll(final BiFunction<? super String, ? super T, ? extends T> function)
    {
        getMap().replaceAll(new BiFunction<CaseInsensitiveMapKey, T, T>()
        {
            @Override
            public T apply(CaseInsensitiveMapKey lookupKey, T t)
            {
                return function.apply(lookupKey.key,t);
            }
        });
    }

    @Override
    public T putIfAbsent(String key, T value)
    {
        return getMap().putIfAbsent(lookupKey(key), value);
    }

    @Override
    public boolean remove(Object key, Object value)
    {
        return getMap().remove(lookupKey(key), value);
    }

    @Override
    public boolean replace(String key, T oldValue, T newValue)
    {
        return getMap().replace(lookupKey(key), oldValue, newValue);
    }

    @Override
    public T replace(String key, T value)
    {
        return getMap().replace(lookupKey(key), value);
    }

    @Override
    public T computeIfAbsent(String key, final Function<? super String, ? extends T> mappingFunction)
    {
        return getMap().computeIfAbsent(lookupKey(key), new Function<CaseInsensitiveMapKey, T>()
        {
            @Override
            public T apply(CaseInsensitiveMapKey lookupKey)
            {
                return mappingFunction.apply(lookupKey.key);
            }
        });
    }

    @Override
    public T computeIfPresent(String key, final BiFunction<? super String, ? super T, ? extends T> remappingFunction)
    {
        return getMap().computeIfPresent(lookupKey(key), new BiFunction<CaseInsensitiveMapKey, T, T>()
        {
            @Override
            public T apply(CaseInsensitiveMapKey lookupKey, T t)
            {
                return remappingFunction.apply(lookupKey.key, t);
            }
        });
    }

    @Override
    public T compute(String key, final BiFunction<? super String, ? super T, ? extends T> remappingFunction)
    {
        return getMap().compute(lookupKey(key), new BiFunction<CaseInsensitiveMapKey, T, T>()
        {
            @Override
            public T apply(CaseInsensitiveMapKey lookupKey, T t)
            {
                return remappingFunction.apply(lookupKey.key,t);
            }
        });
    }

    @Override
    public T merge(String key, T value, BiFunction<? super T, ? super T, ? extends T> remappingFunction)
    {
        return getMap().merge(lookupKey(key), value, remappingFunction);
    }

    protected  Map<CaseInsensitiveMapKey,T> getMapImplementation() {
        return new HashMap<>();
    }

    private Map<CaseInsensitiveMapKey,T> getMap() {
        if (map == null)
            map = getMapImplementation();
        return map;
    }

    private CaseInsensitiveMapKey lookupKey(Object key)
    {
        return new CaseInsensitiveMapKey((String)key);
    }

    public class CaseInsensitiveMapKey {
        private String key;
        private String lookupKey;

        public CaseInsensitiveMapKey(String key)
        {
            this.key = key;
            this.lookupKey = key.toUpperCase();
        }

        @Override
        public boolean equals(Object o)
        {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            CaseInsensitiveMapKey that = (CaseInsensitiveMapKey) o;

            return lookupKey.equals(that.lookupKey);

        }

        @Override
        public int hashCode()
        {
            return lookupKey.hashCode();
        }
    }

    private class KeySet implements Set<String> {

        private Set<CaseInsensitiveMapKey> wrapped;

        public KeySet(Set<CaseInsensitiveMapKey> wrapped)
        {
            this.wrapped = wrapped;
        }


        private List<String> keyList() {
            return stream().collect(Collectors.toList());
        }

        private Collection<CaseInsensitiveMapKey> mapCollection(Collection<?> c) {
            return c.stream().map(it -> lookupKey(it)).collect(Collectors.toList());
        }

        @Override
        public int size()
        {
            return wrapped.size();
        }

        @Override
        public boolean isEmpty()
        {
            return wrapped.isEmpty();
        }

        @Override
        public boolean contains(Object o)
        {
            return wrapped.contains(lookupKey(o));
        }

        @Override
        public Iterator<String> iterator()
        {
            return keyList().iterator();
        }

        @Override
        public Object[] toArray()
        {
            return keyList().toArray();
        }

        @Override
        public <T> T[] toArray(T[] a)
        {
            return keyList().toArray(a);
        }

        @Override
        public boolean add(String s)
        {
            return wrapped.add(lookupKey(s));
        }

        @Override
        public boolean remove(Object o)
        {
            return wrapped.remove(lookupKey(o));
        }

        @Override
        public boolean containsAll(Collection<?> c)
        {
            return keyList().containsAll(c);
        }

        @Override
        public boolean addAll(Collection<? extends String> c)
        {
            return wrapped.addAll(mapCollection(c));
        }

        @Override
        public boolean retainAll(Collection<?> c)
        {
            return wrapped.retainAll(mapCollection(c));
        }

        @Override
        public boolean removeAll(Collection<?> c)
        {
            return wrapped.removeAll(mapCollection(c));
        }

        @Override
        public void clear()
        {
            wrapped.clear();
        }

        @Override
        public boolean equals(Object o)
        {
            return wrapped.equals(lookupKey(o));
        }

        @Override
        public int hashCode()
        {
            return wrapped.hashCode();
        }

        @Override
        public Spliterator<String> spliterator()
        {
            return keyList().spliterator();
        }

        @Override
        public boolean removeIf(Predicate<? super String> filter)
        {
            return wrapped.removeIf(new Predicate<CaseInsensitiveMapKey>()
            {
                @Override
                public boolean test(CaseInsensitiveMapKey lookupKey)
                {
                    return filter.test(lookupKey.key);
                }
            });
        }

        @Override
        public Stream<String> stream()
        {
            return wrapped.stream().map(it -> it.key);
        }

        @Override
        public Stream<String> parallelStream()
        {
            return wrapped.stream().map(it -> it.key).parallel();
        }

        @Override
        public void forEach(Consumer<? super String> action)
        {
            wrapped.forEach(new Consumer<CaseInsensitiveMapKey>()
            {
                @Override
                public void accept(CaseInsensitiveMapKey lookupKey)
                {
                    action.accept(lookupKey.key);
                }
            });
        }
    }

    private class EntrySet implements Set<Map.Entry<String,T>> {

        private Set<Entry<CaseInsensitiveMapKey,T>> wrapped;

        public EntrySet(Set<Entry<CaseInsensitiveMapKey,T>> wrapped)
        {
            this.wrapped = wrapped;
        }


        private List<Map.Entry<String,T>> keyList() {
            return stream().collect(Collectors.toList());
        }

        private Collection<Entry<CaseInsensitiveMapKey,T>> mapCollection(Collection<?> c) {
            return c.stream().map(it -> new CaseInsensitiveEntryAdapter((Entry<String,T>)it)).collect(Collectors.toList());
        }

        @Override
        public int size()
        {
            return wrapped.size();
        }

        @Override
        public boolean isEmpty()
        {
            return wrapped.isEmpty();
        }

        @Override
        public boolean contains(Object o)
        {
            return wrapped.contains(lookupKey(o));
        }

        @Override
        public Iterator<Map.Entry<String,T>> iterator()
        {
            return keyList().iterator();
        }

        @Override
        public Object[] toArray()
        {
            return keyList().toArray();
        }

        @Override
        public <T> T[] toArray(T[] a)
        {
            return keyList().toArray(a);
        }

        @Override
        public boolean add(Entry<String,T> s)
        {
            return wrapped.add(null );
        }

        @Override
        public boolean remove(Object o)
        {
            return wrapped.remove(lookupKey(o));
        }

        @Override
        public boolean containsAll(Collection<?> c)
        {
            return keyList().containsAll(c);
        }

        @Override
        public boolean addAll(Collection<? extends Entry<String,T>> c)
        {
            return wrapped.addAll(mapCollection(c));
        }

        @Override
        public boolean retainAll(Collection<?> c)
        {
            return wrapped.retainAll(mapCollection(c));
        }

        @Override
        public boolean removeAll(Collection<?> c)
        {
            return wrapped.removeAll(mapCollection(c));
        }

        @Override
        public void clear()
        {
            wrapped.clear();
        }

        @Override
        public boolean equals(Object o)
        {
            return wrapped.equals(lookupKey(o));
        }

        @Override
        public int hashCode()
        {
            return wrapped.hashCode();
        }

        @Override
        public Spliterator<Entry<String,T>> spliterator()
        {
            return keyList().spliterator();
        }

        @Override
        public boolean removeIf(Predicate<? super Entry<String, T>> filter)
        {
            return wrapped.removeIf(new Predicate<Entry<CaseInsensitiveMapKey, T>>()
            {
                @Override
                public boolean test(Entry<CaseInsensitiveMapKey, T> entry)
                {
                    return filter.test(new FromCaseInsensitiveEntryAdapter(entry));
                }
            });
        }

        @Override
        public Stream<Entry<String,T>> stream()
        {
            return wrapped.stream().map(it -> new Entry<String, T>()
            {
                @Override
                public String getKey()
                {
                    return it.getKey().key;
                }

                @Override
                public T getValue()
                {
                    return it.getValue();
                }

                @Override
                public T setValue(T value)
                {
                    return it.setValue(value);
                }
            });
        }

        @Override
        public Stream<Map.Entry<String,T>> parallelStream()
        {
            return StreamSupport.stream(spliterator(), true);
        }

        @Override
        public void forEach(Consumer<? super Entry<String, T>> action)
        {
            wrapped.forEach(new Consumer<Entry<CaseInsensitiveMapKey, T>>()
            {
                @Override
                public void accept(Entry<CaseInsensitiveMapKey, T> entry)
                {
                    action.accept(new FromCaseInsensitiveEntryAdapter(entry));
                }
            });
        }
    }

    private class EntryAdapter implements Map.Entry<String,T> {
        private Entry<String,T> wrapped;

        public EntryAdapter(Entry<String, T> wrapped)
        {
            this.wrapped = wrapped;
        }

        @Override
        public String getKey()
        {
            return wrapped.getKey();
        }

        @Override
        public T getValue()
        {
            return wrapped.getValue();
        }

        @Override
        public T setValue(T value)
        {
            return wrapped.setValue(value);
        }

        @Override
        public boolean equals(Object o)
        {
            return wrapped.equals(o);
        }

        @Override
        public int hashCode()
        {
            return wrapped.hashCode();
        }


    }

    private class CaseInsensitiveEntryAdapter implements Map.Entry<CaseInsensitiveMapKey,T> {

        private Entry<String,T> wrapped;

        public CaseInsensitiveEntryAdapter(Entry<String, T> wrapped)
        {
            this.wrapped = wrapped;
        }

        @Override
        public CaseInsensitiveMapKey getKey()
        {
            return lookupKey(wrapped.getKey());
        }

        @Override
        public T getValue()
        {
            return wrapped.getValue();
        }

        @Override
        public T setValue(T value)
        {
            return wrapped.setValue(value);
        }
    }

    private class FromCaseInsensitiveEntryAdapter implements Map.Entry<String,T> {

        private Entry<CaseInsensitiveMapKey,T> wrapped;

        public FromCaseInsensitiveEntryAdapter(Entry<CaseInsensitiveMapKey, T> wrapped)
        {
            this.wrapped = wrapped;
        }

        @Override
        public String getKey()
        {
            return wrapped.getKey().key;
        }

        @Override
        public T getValue()
        {
            return wrapped.getValue();
        }

        @Override
        public T setValue(T value)
        {
            return wrapped.setValue(value);
        }
    }


}

0

Bu nedenle, her olay için yeni bir CaseInsensitiveString nesnesi oluşturuyorum. Yani, performansı etkileyebilir.

Arama yapmadan önce sarmalayıcılar oluşturma veya anahtarı küçük harfe dönüştürme, yeni nesneler oluşturur. Bundan kaçınmanın tek yolu kendi java.util.Map uygulamanızı yazmaktır. Çok zor değil ve IMO buna değer. Aşağıdaki karma fonksiyonunun birkaç yüz tuşa kadar oldukça iyi çalıştığını gördüm.

static int ciHashCode(String string)
{
    // length and the low 5 bits of hashCode() are case insensitive
    return (string.hashCode() & 0x1f)*33 + string.length();
}

-3

Java 8 akışlarını kullanmaya ne dersiniz?

nodeMap.entrySet().stream().filter(x->x.getKey().equalsIgnoreCase(stringfromEven.toString()).collect(Collectors.toList())

Bu, haritadaki değerleri büyük / küçük harfe duyarlı olmayan bir şekilde aramanızı sağlamaz.
Gili

equalsignorecase bunu yapar değil mi?
Amarendra Reddy

Bir liste oluşturuyorsun. OP bir harita istedi.
Gili

Bu, bir haritanın O (1) karmaşıklık avantajını yok eder.
Paul Rooney
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.