HashSet где метод get(Object object) ?!

 
 
 
Сообщения:49
Добрый ! У класса HashSet операции add, remove, contain имеют скорость O(1) . И это очень хорошо, но вот странность, рассмотрим ниже пример:
HashSet<Dog> set = new HashSet<>();
		Dog dog1 = new Dog("Max", 5, 1000);
		Dog dog2 = new Dog("Lord", 7, 2000);
		Dog dog3 = new Dog("Max2", 5, 3000);
		
		set.add(dog1);
		set.add(dog2);
		set.add(dog3);
		System.out.println(set);

где, где Dog(String имя, int возраст, int цена) , у которого и hashCode() и equals() завязаны только на поле "возраст". Поэтому с точки зрения set , dog1 и dog3 это одно и тоже и dog3 уже не будет помещен во множество.
теперь мы хотим удалить, скажем dog1 из set, делаем так:
set.remove(dog3);

Да, у нас ссылка на другой объект , но удаляется dog1 все из-за тех же hashCod() и equals()
Надо проверить наличие, без проблем:
set.contains(dog3);


Однако если возникнет задача - дайте мне ссылку конкретно на dog1, который непосредственно хранится в set, то вариант один - создаем итератор и линейным обходом ищем нужный объект и таким образом получаем на него ссылку. Однако в таком случае мы имеем скорость O(n) , да и то еще надо все пустые бакеты обойти.
Напрашивается некий метод get(Object object) , который будет также опираться на поиск индекса в массиве на основе hashCode и далее на сравнении equals. реализуется по тем же принципам что скажем и remove. И тогда мы бы получили легко Dog tempDog = set.get(dog3) прямая ссылка на dog1, со скорость. О(1)

Почему в java так не сделали?!
Уверен это обсуждалось при разработке класса. Так как на текущий момент получается, что HashSet вообще не подходит в качестве хранилища объектов - то есть мы не можем быстро получить ссылку на какой-либо объект в нем. А подходит только как хранение эталонных объектов, предназначенных для сравнения с другими объектами из других хранилищ ( метод contain(object) )
Изменен:03 авг 2019 13:55
 
 
Сообщения:9843
HashSet он на то и HashSet что работает с equals() & hashCode(). Если объекты равны по equals(), значит они равны для такой коллекции. Если хочется чтоб работало именно по ссылкам, то не нужно переопределять equals() & hashCode().

Еще один вариант - использовать IdentityHashMap. К сожалению IdentityHashSet не был написан, но можно использовать мапу и все значения указывать в null.

А если же нужно по одному объекту получить другой объект - это Мапа, а не Set. В качестве ключа у такой мапы будет как правило ID объекта (в твоем случае это возраст).
Изменен:03 авг 2019 14:01
 
 
Сообщения:49
И все же непонятно, почему они не сделали такой очевидным метод?
То что переопределено hashCode() и equals() - это для наглядности. Сформулирую более общий случай:

Есть HashSet<MyObject> set , в котором один из MyObject object = new MyObject(field1, field2, field3, field4, ... ) . И проблема в том, что у меня нет ссылки на этот самый object. А мне очень ее хочется чтобы, что нить такое с ним сделать, изменить его состояние например.

Так вот на данный момент ее можно получить только с помощью линейного обхода всего массива и сравнивая с каждым объектом хранящимся во множестве через Итератор. Но на минуточку! У меня в классе уже есть быстрый алгоритм поиска ячейки в массиве на основе хешкода, а тут мы собрались пешком обходить всю коллекцию.
Вот я о чем ))))) Почему так сделали ? делов на 2 минуты буквально, зато какой профит.
Изменен:03 авг 2019 14:33
 
 
Сообщения:9843
krogot88:
И все же непонятно, почему они не сделали такой очевидным метод?
За 11 лет работы с Java мне никогда не нужен был такой метод. Более того за все это время я впервые слышу такой вопрос (хотя я сижу на этом форуме, на StackOverflow и общаюсь с коллегами). Так что я бы не спешил называть такой метод очевидным.
krogot88:
Есть HashSet<MyObject> set , в котором один из MyObject object = new MyObject(field1, field2, field3, field4, ... ) . И проблема в том, что у меня нет ссылки на этот самый object. А мне очень ее хочется чтобы, что нить такое с ним сделать, изменить его состояние например.
Еще раз - это Map, а не Set.
 
 
Сообщения:49
Староверъ, спасибо за ответ.
 
 
Сообщения:267
Я тоже ловил себя на мысли, что мне бы надо сделать get из Set =)

Но как правило, множества используются для работы с небольшими наборами объектов, так что нет никаких проблем чтобы пробежаться по ним в случае необходимости.

"Мы же профессионалы! Мы всегда делаем чуть больше, чем требуется!" (с)
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет