Почему 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

потому что часто бывает полезно узнать, действительно ли что-то было добавлено или, напротив, уже было там.