场景:创建一个服务器,其中包含 Room 对象,其中包含用户对象。
我想通过 Id (一个字符串)将房间存储在某种 Map 中。
所需行为:
当用户通过服务器发出请求时,我应该可以从库中查找房间ID,然后将用户添加到房间,如果这是请求所需的。
目前我在我的Library.java类中使用静态函数,其中存储了Map以检索房间:
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中的相同对象具有相同的引用;但是,它不是那样的。有没有办法得到这种行为?也许用某种包装?我只是使用错误的地图变体吗?
帮助?
答案 0 :(得分:2)
您将myRooms
声明为Hashtable<String, Rooms>
(复数Rooms
),但put
Room r
中addRoom
为Map<K,Set<V>>
,这是非常奇怪的。
您是否尝试进行某种多重映射,其中一个键可以映射到多个值?如果是这样,那么请使用Guava实现,或将您自己的实现作为get
(将键映射到 set 的值)。
正确的是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
标记,因此,如果您确实需要HashMap
功能,则可以使用Collections.synchronizedMap
在任何一种情况下,无论您使用Hashtable
还是myRooms
,都希望将Map
简单地声明为{{1}}(请参阅 Effective Java 2nd Edition,第52项:通过接口引用对象)。
答案 1 :(得分:0)
你的代码甚至可以编译吗?
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
代码。