Две карты HashMap «делятся» одними и теми же данными? - PullRequest
1 голос
/ 13 июля 2020

У меня проблема, вероятно, из-за моей неопытности в отношении HashMaps. По сути, у меня есть класс, который содержит две переменные HashMap:

private Map <String, List<String>> definiciones = new <String, List<String>> HashMap();
private Map <String, List<String>> sinonimos = new <String, List<String>> HashMap();

Они хранят строки в своих списках, когда я вызываю их соответствующие функции. Проблема в том, что, например, когда я добавляю строку в список внутри карты определений, она также каким-то образом появляется в sinonimos.

public void agregarDefinicionAPalabra(String palabra, String definicion) throws PalabraInvalida {
    System.out.println(definiciones.get(palabra).size());
    if(definicion.equals("")) {
        JOptionPane.showMessageDialog(null, "La definición no puede estar vacía");
        throw new PalabraInvalida("La definición no puede estar vacía");
    }

    if (definiciones.containsKey(palabra)) {
        definiciones.get(palabra).add(definicion);
    } else {
        throw new PalabraInvalida("No se ha encontrado la palabra solicitada");
    }
    System.out.println(sinonimos.get(palabra).get(0));
}

Метод добавляет строку в список определений, как вы можете видеть , в конце я поставил оттиск, подтверждающий эту идею, которую только что написал. Действительно, когда я запускаю этот метод, список sinonimos получает добавленный мной элемент Definiciones. Очевидно, есть кое-что, чего я не знаю из-за моей неопытности в этом топи c, есть предложения?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 13 июля 2020

Вероятно, вы поместили один и тот же объект списка в обе свои HashMap. В Java все объекты ссылаются на их адрес в памяти. Когда вы помещаете список в свою HashMap, он на самом деле просто сохраняет адрес в памяти списка.

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

Итак, в коде, который создает списки, убедитесь, что вы создали отдельные , отдельные списки для двух карт.

1 голос
/ 27 июля 2020

Диаграмма

Два других ответа верны. Я добавлю этот график c, чтобы визуализировать проблему и решение.

diagram

Copy the list

Or if you want the second list to be based on contents of the first, make a copy. To make a copy, feed the first list to the constructor of the second list.

sinonimos.set( palabra , new ArrayList<>( firstArrayList ) ) ;

An entirely new and separate list is created. But the elements in both lists point to the same content objects. So be aware of those element objects being mutable or неизменяемый .

1 голос
/ 13 июля 2020

Я думаю, вы должны использовать один и тот же объект List для значения на картах definiciones и sinonimos. Например, вы должны сделать что-то вроде:

String palabara = "example";
List<String> list = new ArrayList<>();
definiciones.set(palabra, list);
sinonimos.set(palabra, list);

Что происходит здесь, так это то, что теперь у вас есть тот же список, что и значение на обеих картах. Поэтому, когда вы вызываете definiciones.get(palabra) и sinonimos.get(palabra), оба они дадут вам ссылки на один и тот же список в памяти.

Вместо этого вам нужно сделать:

String palabara = "example";
definiciones.set(palabra, new ArrayList<>());
sinonimos.set(palabra, new ArrayList<>());
...