Java LinkedHashMap: какая разница в этих двух? - PullRequest
4 голосов
/ 01 марта 2010

РЕДАКТИРОВАТЬ: весь код и сценарий создания базы данных можно найти в http://gitorious.org/scheator. Скрипт базы данных находится в схеме / .

У меня есть следующий код Java:

LinkedHashMap, определенный в абстрактном классе как

LinkedHashMap<Object, Data> list;

Класс-потомок, который инициализирует этот список следующим образом:

list = new LinkedHashMap<Integer, Data>();

Я добавляю такие вещи, как это:

    String id = rs.getString(FIELDS[0]);
    String name = rs.getString(FIELDS[1]);
    Data team = new Data(Integer.parseInt(id.trim()), name);
    list.put(id, team);

Теперь, когда я делаю это:

    System.err.println("delete() count: " + list.size());

    System.err.println("delete() key value " + key);
    Data obj;
    obj = (Data)list.remove(key);
    deletedList.put(key, obj);
    System.err.println("delete() count: " + list.size());

Ничего не удаляется из списка, т. Е. Первый и последний отпечатки печатаются одинакового размера (). Ключ также правильный (я проверял, что есть элемент с этим идентификатором).

Однако, и это мой вопрос, если я добавлю такие значения:

    Integer id = rs.getInt(FIELDS[0]);
    String name = rs.getString(FIELDS[1]);
    Data team = new Data(id, name);
    list.put(id, team);

Код работает! Разве parseInt () не должен создавать аналогичный ключ для getInt ()? Почему вторая версия работает, а первая нет? Я потратил целый час на отладку, пока не нашел причину, и до сих пор не могу понять причину.

Ответы [ 5 ]

2 голосов
/ 01 марта 2010

Первый пример:

String id = rs.getString(FIELDS[0]);

Второй пример:

Integer id = rs.getInt(FIELDS[0]);

Не могу сказать наверняка, так как не вижу остальной код, но если в этом вызове переменная key является целым числом:

obj = (Data)list.remove(key);

, тогда удаление будет работать, только если объект был помещен в карту с помощью Integer, и поэтому он работает только тогда, когда id является целым числом, когда вы вызываете метод put. Строка "123" не равна целому числу 123.

Также я предполагаю, что вы просто пропустили строку в первом примере, но не было вызова list.put (id, team), но это также может быть источником ваших проблем

2 голосов
/ 01 марта 2010

Не должно быть никакой разницы, но есть ряд вещей, которые не ясны из вашего примера:

  • deletedList не относится к list объекту
  • записи в вашей базе данных, которые используются в обоих случаях, одинаковы (возможно, в первом случае используется другой объект int, уже находящийся на карте)

Автобокс также может осложнить проблему. Замените Integer id во втором примере на int id, чтобы передать те же аргументы вашему конструктору Data.

Может быть, вы могли бы опубликовать полный код, чтобы мы могли точно воспроизвести сценарий?


Обновление

Вы используете строковые значения в качестве ключей в исходном коде. Затем у вас есть ключ Object в вашем методе remove (key), поэтому я ожидаю, что в этот момент вы передаете Integer метод. Строка не будет совпадать с целым числом как ключом, что объясняет, почему ваше удаление не работало.

Если вы используете generics для указания вашей HashMap (LinkedHashMap<Integer, Team> вместо <Object, Team>), такого рода ошибки не произойдет - компилятор скажет что-то вроде

The method put(Integer, Object) in the type HashMap<Integer,Object> is not applicable for the arguments (String, String)

1 голос
/ 01 марта 2010

Янамон прав. Это довольно ясно, когда вы смотрите на diff :

             while (rs.next()) {
-                String id = rs.getString(FIELDS[0]);
+                Integer id = rs.getInt(FIELDS[0]);
                 String name = rs.getString(FIELDS[1]);
-                Data team = new Data(Integer.parseInt(id.trim()), name);
+                Data team = new Data(id, name);
                 list.put(id, team);

Обратите внимание, что в исходной версии int (автоматически упаковывается в Integer) передается в конструктор Data. Но id, который помещается, по-прежнему является String.

0 голосов
/ 01 марта 2010

На вашем месте я бы проверил содержимое LinkedHashMap с помощью отладчика, до и после вашего пута, а также до и после вашего удаления. Войдите в метод remove() (исходный код является частью JDK) и посмотрите, что он делает. Скорее всего, ваш код неправильно добавляет или удаляет объект. Здесь трудно увидеть, потому что пример кода неполон.

Что касается rs.getInt() и Integer.parseInt(), первое относится к поставщику базы данных (я предполагаю, что rs равно ResultSet), и, таким образом, они могут не работать одинаково. Однако после того, как ключ Integer создан (вы можете проверить это с помощью отладчика), он должен быть эквивалентен для целей HashMap или LinkedHashMap. Но ваш пример кода усложняет ситуацию; вы используете rs.getString(), а затем Integer.parseInt(). Хотя я был бы удивлен, если бы это произошло, возможно, драйвер базы данных форматирует столбец id в строку, которая сбивает с толку parseInt(). Для меня гораздо удобнее просто сделать rs.getInt().

0 голосов
/ 01 марта 2010

Я предполагаю, что во втором случае вы явно преобразуете его в целое число

Integer id = rs.getInt(FIELDS[0]);

в то время как в первом случае он остается целым

Integer.parseInt(id.trim())

от javadoc parseInt

static int  parseInt(String s) 
Parses the string argument as a signed decimal integer.
...