почему метод replace () не определен в интерфейсе Set? - PullRequest
21 голосов
/ 14 апреля 2010

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

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

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

Ответы [ 5 ]

16 голосов
/ 14 апреля 2010

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

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

5 голосов
/ 14 апреля 2010

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

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

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

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

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

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

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

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

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

2 голосов
/ 14 апреля 2010

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

Из документов :

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

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

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

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

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

1 голос
/ 14 апреля 2010

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

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

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

1 голос
/ 14 апреля 2010

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

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