Почему List.add(E) возвращает boolean, а List.Add(int, E) возвращает void?
Глядя на javadoc, я увидел, что ArrayList имеет перегруженный метод добавления:
public boolean add (E e)
Добавляет указанный элемент в конец этого списка.
и
public void add (индекс int, E)
Вставляет указанный элемент в указанную позицию в этом списке. Сдвигает элемент в данный момент (если есть) и любые последующие элементы справа (добавляет один к их индексам).
Я заметил, что первая вернула boolean
, а вторая - void
. Как оказалось, первый add
должен возвращать a boolean
, потому что:
Возвращает: true (как указано в Collection.add(E))
Итак, я пошел в Collection.add(E):
boolean add (E e)
Обеспечивает, чтобы эта коллекция содержала указанный элемент (дополнительная операция). Возвращает true, если эта коллекция изменилась в результате вызова. (Возвращает false, если эта коллекция не позволяет дублировать и уже содержит указанный элемент.)
Итак, мой вопрос: почему указано add
для возврата boolean вместо того, чтобы быть пустотой? Когда я add
что-то, я ожидал бы сделать только операцию.
Я понимаю, что существуют другие структуры данных, которые, в отличие от ArrayList, не допускают дубликатов (например, наборов). Но даже тогда проблема не могла быть решена в соответствии с:
public void add(E e){
if(e is not in set){
add e;
}
}
Таким образом, если e
IS в наборе не предпринимается никаких действий. Почему лучше возвращать boolean
вместо подхода void
?
Ответы
Ответ 1
Collection.add
- довольно общий метод (не в смысле Java-дженериков - в смысле широкого применения). Таким образом, они хотели получить возвращаемое значение, которое будет применяться в целом.
Некоторые классы (например, ArrayList
) всегда принимают элементы, поэтому всегда возвращаются true
. Вы правы, что в этих случаях возвращаемый тип void
будет таким же хорошим.
Но другие, такие как Set
, иногда не позволяют добавлять элемент. В случае Set
это происходит, если уже присутствует равный элемент. Часто это полезно знать. Другим примером является ограниченная коллекция (которая может содержать только определенное количество элементов).
Вы можете спросить: "Не можете ли код просто проверить это вручную?" Например, с набором:
if (!set.contains(item)) {
set.add(item);
itemWasAdded(item);
}
Это более подробно, чем то, что вы можете сделать сейчас, но не много:
if (set.add(item)) {
itemWasAdded(item);
}
Но это поведение с поправкой на проверку не является потокобезопасным, что может иметь решающее значение для многопоточных приложений. Например, может быть, что другой поток добавил равный элемент между вами, проверяя set.contains(item)
и set.add(item)
в первом фрагменте кода. В многопоточном сценарии эти два действия действительно должны быть единым, атомным действием; возврат boolean
из метода делает возможным.
Ответ 2
Потому что это дополнительная информация, которая ничего не стоит и может быть полезна в определенных ситуациях. Например:
Set<String> set = new HashSet<String>();
set.add("foobar");
boolean wasAlreadyThere = set.add("foobar");
В противном случае вам придется делать
boolean wasAlreadyThere = set.contains("foobar");
set.add("foobar");
который требует в два раза больше работы (сначала вы должны искать, затем искать снова, чтобы добавить).
Ответ 3
потому что часто бывает полезно узнать, действительно ли что-то было добавлено или, напротив, уже было там.