Bir Hashmap anahtarını yeniden adlandırmak mümkün mü?


92

Hashmap anahtarını yeniden adlandırmanın bir yolunu arıyorum, ancak bunun Java'da mümkün olup olmadığını bilmiyorum.


11
Tanrım, umarım değildir. Anahtar / değer çiftini silmek ve yeniden girmek, yapılacak yol gibi görünüyor. Normalde zaten haritadaki referansları işlediğinizi unutmayın.
Maarten Bodewes

4
Lütfen hash girişinin anahtarını değiştirmeyin! Şanslıysanız, aynı hashcode'a sahip bir şeye değiştirirsiniz ve ne olduğunu anlamaya çalışırken biraz delirirsiniz; Şanssızsanız, bulunamayan bir girişle sonuçlanırsınız (peki, tüm tablonun bir sonraki yeniden oluşturulmasına kadar değil). Kaldır / yeniden yerleştir çok daha mantıklı ve oldukça ucuz olmalı (sonuçta hepsi referanslar).
Donal Fellows

Yanıtlar:


140

Öğeyi kaldırmayı ve yeni adla yeniden koymayı deneyin. Haritanızdaki anahtarların olduğunu varsayarsak, Stringşu şekilde başarılabilir:

Object obj = map.remove("oldKey");
map.put("newKey", obj);

61
+1. Ve okunması en basit olanı map.put( "newKey", map.remove( "oldKey" ) );içerir ve sağlanıroldKey
Ravinder Reddy

15
Okunabilirlik söz konusu olduğunda, kesinlikle katılmıyorum, şahsen bir nesnenin haritadan kaldırılıp eklendiğini açıkça görmeyi tercih ediyorum. Ve OP, Java için oldukça yeni göründüğünden, onu bu şekilde ifade etmeye karar verdim. Ancak performans açısından sizin sürümünüz tercih edilir (çünkü derleyicinin sürümümü sizin yönteminize göre optimize edeceğini düşünmüyorum).
Alexis Pigeon

3
Javac 1.8.0_45 için tek satırlık sürüm, iki bayt kodun daha kısa olması beni şaşırttı. Daha rahatsız edici jenerik ile sen geçemez objiçin putbunu döküm veya başka türü olarak deklare etmeden, ama tabii ki sonucu geçen removedoğrudan çalışır.
Samuel Edwin Ward

1
Ama tüm anahtarlar nasıl yeniden adlandırılır
gstackoverflow

4
ConcurrentModificationException'a yol açacak
gstackoverflow


19

Yeniden adlandırılması gereken anahtarın değerini yeni bir anahtara atayın. Ve eski anahtarı çıkarın.

hashMap.put("New_Key", hashMap.get("Old_Key"));
hashMap.remove("Old_Key");

10

Eklendikten keysonra hashmap'i yeniden adlandıramaz / değiştiremezsiniz .

Tek yol, silmek / çıkarmak keyve yenisi keyve valueçift ile eklemek .

Sebep : Hashmap dahili uygulamasında Hashmapkeydeğiştiricisi olarak işaretlenmişfinal.

static class Entry<K ,V> implements Map.Entry<K ,V>
{
    final K key;
    V value;
    Entry<K ,V> next;
    final int hash;
    ...//More code goes here
}

Referans için: HashMap


Bir anahtarı yeniden adlandırmak mümkün olmadığından bence en iyi yanıt budur .
Wolfson

4

Bir hashmap anahtarını yeniden adlandırmazsınız, yeni anahtarla yeni bir giriş eklemeniz ve eskisini silmeniz gerekir.


2

Hashmap anahtarlarının özünün indeks erişim amaçları için olduğunu ve başka bir şey olmadığını iddia ediyorum ama burada bir hack var: anahtar sarmalayıcı nesnesi indeks erişimi için hashmap anahtarı haline gelecek şekilde anahtarın değeri etrafında bir anahtar sarmalayıcı sınıfı yapmak, yani özel ihtiyaçlarınız için anahtar sarmalayıcı nesnesinin değerine erişebilir ve bunları değiştirebilir:

public class KeyWrapper<T>{

      private T key;
      public KeyWrapper(T key){
         this.key=key;
       }

      public void rename(T newkey){
              this.key=newkey;
       }

}

Misal

   HashMap<KeyWrapper,String> hashmap=new HashMap<>();
   KeyWrapper key=new KeyWrapper("cool-key");
   hashmap.put(key,"value");
   key.rename("cool-key-renamed");

Var olmayan bir anahtara da sahip olsanız da, hashmap'ten mevcut bir anahtarın değerini alabilmeniz için, yine de bunun suç olabileceğinden korkuyorum:

public  class KeyWrapper<T>{

        private T key;
        public KeyWrapper(T key){
            this.key=key;
        }

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

        @Override
        public int hashCode() {
            int hash=((String)key).length();//however you want your hash to be computed such that two different objects may share the same at some point
            return hash;
        }
    }

Misal

HashMap<KeyWrapper,String> hashmap=new HashMap<>();
KeyWrapper cool_key=new KeyWrapper("cool-key");
KeyWrapper fake_key=new KeyWrapper("fake-key");
hashmap.put(cool_key,"cool-value");
System.out.println("I don't believe it but its: "+hashmap.containsKey(fake_key)+" OMG!!!");

1

Lütfen aşağıdaki noktalara bakın:

  1. Hayır, yeniden adlandırabilir edemez keyait HashMapkatma kez.

  2. Çok öncelikle silmek veya kaldırmak zorunda keyve ardından yeni ekleyebileceğin keyile value.

  3. Çünkü HashMapdahili uygulamada HashMapanahtar değiştirici final.


0

Java yerel HashMap yerine bir Bimap kullanacaksanız, yapabilirsiniz .
Bu geleneksel Harita uygulaması değildir ve ihtiyaçlarınıza uygun olduğundan emin olmanız gerekir.

Bir bimap (veya "çift yönlü harita"), değerlerinin ve anahtarlarının benzersizliğini koruyan bir haritadır. Bu kısıtlama, bimap'lerin, bu bimap ile aynı girdileri içeren ancak tersine çevrilmiş anahtarlar ve değerlere sahip başka bir bimap olan "ters görünümü" desteklemesini sağlar.

Bir bimap kullanarak görünümü tersine çevirebilir ve anahtarı değiştirebilirsiniz.
Hem Apache Commons BidiMap hem de Guava BiMap'e göz atın .


0

Benim durumumda gerçek anahtar içermeyen bir harita vardı -> gerçek anahtarlar, bu yüzden gerçek olmayanları haritamdaki gerçeklerle değiştirmek zorunda kaldım (fikir diğerleri gibi)

getFriendlyFieldsMapping().forEach((friendlyKey, realKey) ->
    if (map.containsKey(friendlyKey))
        map.put(realKey, map.remove(friendlyKey))
);
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.