Есть ли в Java карта, которая поддерживает поиск ключей по (неуникальному) значению? - PullRequest
0 голосов
/ 27 января 2020

У меня есть установка, в которой каждый из моих «Людей» отображается на определенную c «Комнату».

Однако несколько человек могут сопоставить одну и ту же комнату.

Если существующий человек виден, его комната должна быть обновлена ​​до нового значения.

Так что это традиционный вариант использования для Map<Person, Room>.put(Person, Room)

Однако, поиск всегда будет "Какие люди в этой комнате? Set<People> get(Room q){}

Очевидно, я могу создать свою собственную структуру данных или просто перебрать пары ключ-значение ; но имеет ли одна из библиотек Java коллекций хорошую структуру для поддержки ссылочной целостности и поиска, которые мне нужны?

Ответы [ 3 ]

5 голосов
/ 27 января 2020

Чтобы ответить на заданный вами c вопрос, нет, вы не можете сделать все это с одной структурой данных. Я бы решил это с

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);
}

2 голосов
/ 27 января 2020

При наличии дополнительных бизнес-требований, например, когда один человек может находиться только в одной комнате за раз (от комментариев к вашему вопросу), вам придется вернуться к пользовательской абстракции хранилища данных.

Я бы рекомендовал не раскрывать структуру данных, но предоставлять соответствующие абстракции бизнес-уровня для 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.
0 голосов
/ 27 января 2020

Я считаю, что Guava's Multimap [1] делает то, что вы хотите. Вы можете использовать Room s в качестве ключей и Person s в качестве значений. После этого вы можете получить get(someRoom), чтобы вернуть группу людей в этой комнате.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...