Набор по умолчанию в Java, к сожалению, не предназначен для обеспечения операции get, как точно объяснил jschreiner .
Решения использования итератора для поиска интересующего элемента (предложено dacwe ) или для удаления элемента и его повторного добавления с обновленными значениями (предложено KyleM ), может работать, но может быть очень неэффективным.
Переопределение реализации equals, так что неравные объекты являются «равными», как правильно сказано David Ogren , может легко вызвать проблемы с обслуживанием.
И использование Map в качестве явной замены (как предлагают многие), imho, делает код менее элегантным.
Если цель состоит в том, чтобы получить доступ к исходному экземпляру элемента, содержащегося в наборе (надеюсь, я правильно понял ваш вариант использования), вот еще одно возможное решение.
У меня лично была такая же потребность при разработке видеоигры клиент-сервер с Java. В моем случае у каждого клиента были копии компонентов, хранящихся на сервере, и проблема заключалась в том, что клиенту нужно было изменить объект сервера.
Передача объекта через Интернет означала, что у клиента все равно были разные экземпляры этого объекта. Чтобы сопоставить этот «скопированный» экземпляр с исходным, я решил использовать Java UUID.
Итак, я создал абстрактный класс UniqueItem, который автоматически присваивает случайный уникальный идентификатор каждому экземпляру его подклассов.
Этот UUID используется совместно клиентом и экземпляром сервера, поэтому таким образом можно легко сопоставить их, просто используя Map.
Однако непосредственное использование Карты в аналогичном сценарии использования было все еще не элегантным. Кто-то может возразить, что использование карты может быть более сложным в обслуживании и обработке.
По этим причинам я реализовал библиотеку MagicSet, которая делает использование карты "прозрачным" для разработчика.
https://github.com/ricpacca/magicset
Как и исходный Java HashSet, MagicHashSet (который является одной из реализаций MagicSet, представленных в библиотеке) использует вспомогательный HashMap, но вместо того, чтобы использовать элементы в качестве ключей и фиктивное значение в качестве значений, он использует UUID элемент как ключ и сам элемент как значение. Это не вызывает накладных расходов на использование памяти по сравнению с обычным HashSet.
Более того, MagicSet можно использовать именно как набор, но с некоторыми другими методами, обеспечивающими дополнительные функции, такими как getFromId (), popFromId (), removeFromId () и т. Д.
Единственное требование для его использования - чтобы любой элемент, который вы хотите сохранить в MagicSet, должен расширять абстрактный класс UniqueItem.
Вот пример кода, представляющий, как извлечь исходный экземпляр города из MagicSet, учитывая другой экземпляр этого города с тем же UUID (или даже просто его UUID).
class City extends UniqueItem {
// Somewhere in this class
public void doSomething() {
// Whatever
}
}
public class GameMap {
private MagicSet<City> cities;
public GameMap(Collection<City> cities) {
cities = new MagicHashSet<>(cities);
}
/*
* cityId is the UUID of the city you want to retrieve.
* If you have a copied instance of that city, you can simply
* call copiedCity.getId() and pass the return value to this method.
*/
public void doSomethingInCity(UUID cityId) {
City city = cities.getFromId(cityId);
city.doSomething();
}
// Other methods can be called on a MagicSet too
}