【问题标题】:Why is my Map broken?为什么我的地图坏了?
【发布时间】:2011-02-23 01:52:25
【问题描述】:

场景:创建具有 Room 对象的服务器,其中包含 User 对象。

我想通过 Id(字符串)将房间存储在某种 Map 中。

期望的行为

当用户通过服务器发出请求时,我应该能够通过 id 从库中查找房间,然后将用户添加到房间,如果这是请求需要的话。

目前我在存储地图的 Library.java 类中使用静态函数来检索房间:

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 返回的 Room 多少次,该用户稍后都不在房间内。

我认为在 Java 中,返回的对象本质上是对数据的引用,与 Hashtable 中具有相同引用的相同对象;但是,它的行为并非如此。有没有办法获得这种行为?也许有某种包装?我只是使用了错误的地图变体吗?

帮助?

【问题讨论】:

  • 最好也能看到 Room 的代码。
  • 它会认为,一旦我发布了这个,我就会把这些点连接起来。在 4 个月不看这段代码后,我又回来了。我有一些隐藏在用户中的代码 sn-p 基本上是这样做的: setRoomPseudo(Room r) { if(myRoom != null) myRoom.removeMe() myRoom = r } 所以,我忘记了它是这样工作的并做了操作乱序。已修复,麻烦您了。毕竟我懂地图,还有java,只是我自己不懂!

标签: java multithreading reference map hashtable


【解决方案1】:

您将myRooms 声明为Hashtable&lt;String, Rooms&gt;(复数Rooms)非常奇怪,但您putaddRoom 中却是单数Room r

您是否正在尝试做某种多映射,其中一个键可以映射到多个值?如果是这样,那么我们要么使用Guava 实现,要么实现您自己的Map&lt;K,Set&lt;V&gt;&gt;(将键映射到值的)。

不过,我不确定这是否是您的根本问题。

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 时遇到问题,因为他们的密钥对象没有正确实现hashCodeequals 契约,但如果您使用String 作为密钥,这应该不是问题。

顺便说一句,HashtableHashMap 中有一个更新、更性感的表弟。我注意到问题中的multithreading 标签,所以如果你真的需要synchronized 功能,你可以使用Collections.synchronizedMap

在任何一种情况下,无论您使用HashMap 还是Hashtable,您都希望将myRooms 简单地声明为Map(参见Effective Java 2nd Edition,Item 52:通过对象引用对象)接口)。

相关问题

【讨论】:

  • 它会认为,一旦我发布了这个,我就会把这些点连接起来。在 4 个月不看这段代码后,我又回来了。我有一些隐藏在用户中的代码 sn-p 基本上是这样做的: setRoomPseudo(Room r) { if(myRoom != null) myRoom.removeMe() myRoom = r } 所以,我忘记了它是这样工作的并做了操作乱序。已修复,麻烦您了。毕竟我懂地图,还有java,只是我自己不懂!
【解决方案2】:

你的代码还能编译吗?

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 代码。

【讨论】:

  • 如果Room extends/implements Rooms,它将编译。不过,这很奇特。
  • 它会认为,一旦我发布了这个,我就会把这些点连接起来。在 4 个月不看这段代码后,我又回来了。我有一些隐藏在用户中的代码 sn-p 基本上是这样做的: setRoomPseudo(Room r) { if(myRoom != null) myRoom.removeMe() myRoom = r } 所以,我忘记了它是这样工作的并做了操作乱序。已修复,麻烦您了。毕竟我懂地图,还有java,只是我自己不懂!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
相关资源
最近更新 更多