Почему нет метода replace(), определенного на интерфейсе Set?

В настоящее время мне нужно написать следующее, чтобы обновить элемент, уже содержащийся в Set:

Set mySet= ...
Element e1 = new Element (...);
....
....
Element e2 = new Element (...);
\\e1 and e2 are different instances, but equals.

\\update the element contained into the Set
if (mySet.contains(e2)){
    mySet.remove(e2);
    myset.add(e2);
 }

Это не выглядит красиво. Есть ли альтернатива?

Ответ 1

A Set - это структура данных, созданная для избежания дублирования путем использования equals() для объекта; это также означает, что два объекта, равные() друг другу, считаются абсолютно эквивалентными. То есть, используете ли вы версию уже в наборе или в новой, ваш код должен работать одинаково.

Если вы хотите обновить объект с новым значением, то это явно не относится к вам (обе версии не могут заменить друг друга), и вам следует использовать другую структуру данных (например, карту, где вы можете легко переопределить значение, в этом случае ключ может даже быть самим объектом).

Ответ 2

Почему метод replace() не задан на интерфейсе Set?

Я могу думать о трех причинах:

  • Это функционально избыточно: set.replace(old, nu) просто if (set.remove(old)) { set.add(nu) }, например.

  • Поведение в случае, когда old нет, добавляет сложности.

  • Добавление replace в API Set заставляет все реализации Set реализовать (избыточный) метод.

Возможно даже, что есть более глубокие причины; например делать с реализацией replace в некотором неясном случае.

Однако, как указывали другие, ваш вариант использования вообще не требует replace . Ваш код имеет тот же эффект (*) как это:

    Set myset = ...
    myset.add(element);

(* Фактически, вы можете обнаружить разницу, если ваш метод element.equals(Object) сравнивает поле объектов элемента по полю. В зависимости от реализации Set вы можете получить разные ссылки на объекты в наборах после выполнения двух кодовых последовательностей. Но, ИМО, вы будете задавать проблемы, если делаете предположения об этом!)

Ответ 3

Я думаю, что альтернатива просто используется add.

Из docs:

Добавляет указанный элемент в этот набор если он еще не присутствует (необязательно операция). Более формально добавляет заданный элемент e для этого набора, если множество не содержит элемента e2 такого, что (e == null? e2 == null: e.equals(e2)). Если этот набор уже содержит элемент, вызов выходит из набора неизменен и возвращает false.

Однако я не могу сказать из вашего вопроса, пытаетесь ли вы обновить или заменить элемент. Когда вы изменяете элемент в свойстве, эти изменения автоматически отражаются в Set, потому что Set содержит ссылки, поэтому нет update. Если при попытке заменить другой элемент, такой метод replace будет лишним, как объясняется Stephen C.

(после редактирования вопроса)

e1 и e2 - разные экземпляры, но равно.

Я предлагаю вам реализовать равенство на Element. Таким образом, метод add проверяет существование элемента не по ссылке (по умолчанию Object.equals), а по вашему понятию равенства на Element. Поэтому, даже если ссылки e1 и e2 различны, e1.equals(e2) == true.

Ответ 4

по определению, набор не может содержать элемент более одного раза, поэтому ваш файл contains- > remove- > add бессмыслен. просто добавьте свой товар столько раз, сколько хотите.

Ответ 5

Не нужно удалять, а затем добавлять. Просто измените объект напрямую. Поскольку Sets (или любая коллекция) просто сохраняет ссылку, вам не нужен метод replace().

ИЗМЕНИТЬ: приведенное выше утверждение НЕПРАВИЛЬНО. См. http://java.sun.com/j2se/1.4.2/docs/api/java/util/Map.html

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