Java 中是否有支持按(非唯一)值查找键的映射?

Is there a Map in Java that supports looking up Keys by (non-Unique) Value?

我有一个设置,其中我的每个 "People" 映射到特定的 "Room"。

但是,多人可以映射到同一个房间。

如果看到现有人员,他们的房间应更新为新值。

所以这是 Map<Person, Room>.put(Person, Room)

的传统用例

但是,查找总是 "Which people are in this room?" Set<People> get(Room q){}

我显然可以制作自己的数据结构或 simply iterate over the key-value pairs;但是 其中一个 Java 集合库是否具有良好的结构来支持我需要的引用完整性和查找?

有额外的业务需求,例如一个人一次只能在一个房间里(从评论到你的问题),你将不得不恢复到数据存储的自定义抽象。

我建议不要公开数据结构,而是为 Rooms 和 People 提供适当的业务级别抽象。在实现中,你要做的不仅仅是将东西存储在简单的集合中,例如检查业务规则。评论已经给出了一些指示,但我的建议是停止从标准集合的角度考虑问题。

请注意,考虑到并发性,您仍然可以最终看到一个人出现在两个房间中:

List<Person> people1 = ...getPeopleInRoom(1);
// concurrent changes here, in a different thread: somebody changes rooms
List<Person> people2 = ...getPeopleInRoom(2);

// you now may have the same person in two different lists - 
// because when you asked for the occupants in a room, they 
// were in the given room, but no longer are.

要回答您的具体问题,不,您不能用一种数据结构完成所有工作。我会用

来解决
Map<Person,Room> personRoom;
SetMultimap<Room,Person> roomPeople;
void addPersonToRoom(Person p,Room r){
    Room currentRoom = personRoom.get(p);
    if (currentRoom != null)
        roomPeople.remove(currentRoom, p);
    personRoom.put(p,r);
    roomPeople.put(r,p);
}
Set<Person> getPeopleInRoom(Room r){
    return roomPeople.get(r);
}
Room getRoomForPerson(Person p){
    return personRoom.get(p);
}

我相信 Guava 的 Multimap [1] 可以满足您的需求。您可以使用 Rooms 作为键,使用 Persons 作为值。然后你可以让 get(someRoom) 到 return 那个房间里的一组人。

[1] https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap