Можно ли переименовать ключ Hashmap?


92

Я ищу способ переименовать ключ Hashmap, но не знаю, возможно ли это в Java.


11
Гоша, надеюсь, что нет. Удаление и повторный ввод пары ключ / значение кажется правильным решением. Обратите внимание, что вы обычно все равно обрабатываете ссылки на самой карте.
Маартен Бодевес

4
Пожалуйста, не изменяйте ключ хеш-записи! Если вам повезет, вы замените его на что-то с тем же хэш-кодом и просто сойдете с ума, пытаясь выяснить, что произошло; если вам не повезет, вы получите запись, которую невозможно найти (ну, не раньше следующего перестроения всей таблицы). Удаление / повторная вставка намного разумнее и должно быть довольно дешевым (в конце концов, это все ссылки).
Donal Fellows

Ответы:


140

Попробуйте удалить элемент и поставить снова с новым именем. Предполагая, что ключи на вашей карте есть String, это может быть достигнуто следующим образом:

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

61
+1. И проще читать, map.put( "newKey", map.remove( "oldKey" ) );и при условии , что содержитoldKey
Ravinder Reddy

15
Что касается удобочитаемости, я совершенно не согласен, я лично предпочитаю четко видеть, что объект удаляется с карты, а затем добавляется. И поскольку OP кажется довольно новым для Java, я решил выразить это так. Однако ради производительности ваша версия, конечно, предпочтительнее (поскольку я не думаю, что компилятор оптимизирует мою версию по-вашему).
Alexis Pigeon

3
Для javac 1.8.0_45 однострочная версия на два байткода короче, что меня удивило. Более раздражающе дженериков вы не можете пройти , objчтобы putбез приведения его или объявить его в качестве другого типа, но, конечно , передавая результат из removeнепосредственно работает.
Сэмюэл Эдвин Уорд

1
Но как переименовать все ключи
gstackoverflow 04

4
Это приведет к исключению ConcurrentModificationException
gstackoverflow 07

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

Это будет делать то, что вы хотите, но вы заметите, что расположение ключа изменилось.


@Vins, пожалуйста, проверьте документацию: D, remove () вернет объект, проверьте этот tutorialspoint.com/java/util/hashmap_remove.htm
Мохамед Закария Эль-Зогби

1
мой плохой, я удалил свой комментарий и проголосовал за него. Прости за это.
Винс

19

Присвойте значение ключа, который нужно переименовать, новому ключу. И удалите старый ключ.

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

10

Вы не можете переименовать / изменить хэш-карту keyпосле добавления.

Единственный способ - удалить / удалить keyи вставить с новым keyи valueпарным.

Причина : во внутренней реализации hashmapkeyмодификаторHashmapпомечен как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
}

Для справки: HashMap


это лучший ответ на мой взгляд , так как это не возможно переименовать ключ.
Вольфсон

4

Вы не переименовываете ключ хэш-карты, вам нужно вставить новую запись с новым ключом и удалить старую.


2

Я бы сказал, что сущность ключей hasmap предназначена для целей доступа к индексу и не более того, но вот хитрость: создание класса-оболочки для ключа вокруг значения ключа, чтобы объект-оболочка для ключа стал ключом хэш-карты для доступа к индексу, поэтому вы может получить доступ и изменить значение объекта обертки ключа для ваших конкретных нужд:

public class KeyWrapper<T>{

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

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

}

пример

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

Хотя у вас также может быть несуществующий ключ, чтобы получить значение существующего ключа из хэш-карты, но я боюсь, что в любом случае это может быть преступным:

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

пример

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

Пожалуйста, смотрите ниже пункты:

  1. Нет, Вы не можете переименовать keyиз HashMapкогда - то добавил.

  2. Сначала вам нужно удалить или удалить это, keyа затем вы можете вставить новый keyс помощью value.

  3. Потому что во HashMapвнутренней реализации HashMapключевой модификатор final.


0

Вы можете, если вместо Java HashMap вы будете использовать Bimap .
Это не традиционная реализация карты, и вам нужно убедиться, что она соответствует вашим потребностям.

Двухсторонняя карта (или «двунаправленная карта») - это карта, которая сохраняет уникальность своих значений, а также уникальность своих ключей. Это ограничение позволяет бимапам поддерживать «инверсный вид», который представляет собой другой бимап, содержащий те же записи, что и этот бимап, но с инвертированными ключами и значениями.

Используя бимап, вы можете перевернуть представление и заменить ключ.
Оформить заказ как Apache Commons BidiMap, так и Guava BiMap .


0

В моем случае была карта, содержащая не настоящий ключ -> реальные ключи, поэтому мне пришлось заменить нереальные числа на реальные на моей карте (идея похожа на другие)

getFriendlyFieldsMapping().forEach((friendlyKey, realKey) ->
    if (map.containsKey(friendlyKey))
        map.put(realKey, map.remove(friendlyKey))
);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.