Почему моя карта сломана? - PullRequest
4 голосов
/ 24 мая 2010

Сценарий : создание сервера с комнатой объектами, которые содержат пользователей объектов.

Я хочу хранить комнаты на карте в некотором роде по Id (строка).

Желаемое поведение :

Когда пользователь отправляет запрос через сервер, я могу найти комнату по идентификатору из библиотеки, а затем добавить пользователя в комнату, если это необходимо для запроса.

В настоящее время я использую статическую функцию в своем классе Library.java, где хранится Карта, для получения Rooms:

public class Library {

  private static Hashtable<String, Rooms> myRooms = new Hashtable<String, Rooms>();

  public static addRoom(String s, Room r) {  
    myRooms.put(s, r);
  }

  public static Room getRoomById(String s) {
    return myRooms.get(s);
  }
}

В другом классе я сделаю эквивалент myRoom.addUser(user);

То, что я наблюдаю с помощью Hashtable, это то, что независимо от того, сколько раз я добавляю пользователя в Комнату, возвращаемую getRoomById, пользователя позже нет в комнате.

Я думал, что в Java возвращенный объект по сути является ссылкой на данные, тем же объектом, который был в Hashtable с теми же ссылками; но это не так. Есть ли способ получить такое поведение? Может быть, с какой-нибудь оберткой? Я просто использую неправильный вариант карты?

Помощь

Ответы [ 2 ]

2 голосов
/ 24 мая 2010

Очень странно, что вы объявляете myRooms как Hashtable<String, Rooms> (множественное число Rooms), но вы put в единственном числе Room r в addRoom.

Вы пытаетесь создать какую-то мультикарту, где ключ может отображаться на несколько значений? Если это так, то либо используйте реализацию Guava , либо реализуйте свою собственную как Map<K,Set<V>> (сопоставьте ключ с набором значений).

Хотя я не уверен, что это ваша основная проблема.

Правильно, что возвращаемое значение get должно быть таким же объектом, как определено равенством ссылок, и тем, который используется в put.

    Object someObject = new Object();
    Map<String,Object> map = new HashMap<String,Object>();
    map.put("key1", someObject);
    System.out.println(map.get("key1") == someObject); // prints "true"

    someObject = "something else";
    System.out.println(map.get("key1") == someObject); // prints "false"

Выше приведено ожидаемое поведение.

Иногда у людей возникают проблемы с Map, потому что их ключевые объекты не реализуют hashCode и equals контракт должным образом, но если вы используете String в качестве ключей, это не должно быть проблемой.

Кстати, у Hashtable есть более новая, более сексуальная кузина в HashMap. Я заметил тег multithreading в вопросе, поэтому, если вам действительно нужна функция synchronized, вы можете использовать Collections.synchronizedMap

В любом случае, независимо от того, используете ли вы HashMap или Hashtable, вы хотите объявить myRooms просто как Map (см. Effective Java 2nd Edition, Item 52: Ссылки на объекты по интерфейсы ).

Смежные вопросы

0 голосов
/ 24 мая 2010

Ваш код даже компилируется?

public class Library {

  private static Hashtable<String, Rooms> myRooms = new Hashtable<String, Rooms>();

  public static addRoom(String s, Room r) { // Your hashtable holds Rooms yet you add a Room
    myRooms.put(s, r);
  }

  public static Room getRoomById(String s) { // Again, returning a Room, instead of Rooms
    return myRooms.get(s);
  }
}

Просто глядя на это, оно не должно компилироваться. Теперь я могу только предположить, что это была опечатка, и если это так, покажите нам код Room, где вы пытаетесь добавить пользователя в комнату.

...