Add: примеры (JAVA)
add(E e): booleanОбщее описание метода add
В Java под названием add встречается набор одноимённых методов в разных классах и интерфейсах. Наиболее часто употребляемый - Collection.add(E), который добавляет элемент в коллекцию. Поведение и сигнатуры различаются в зависимости от реализации:
- Collection.add(E element) - добавляет элемент в коллекцию. Возвращает
boolean:true, если коллекция изменилась в результате операции,falseдля некоторых реализаций (например,Set, когда элемент уже присутствует). - List.add(int index, E element) - вставляет элемент по индексу. Сигнатура возвращает
void; при неправильном индексе возникаетIndexOutOfBoundsException. - Set.add(E element) - спецификация
Collection.addдля множеств. Возвращаетtrue, если элемент добавлен;false, если элемент уже присутствует (сравнение черезequalsи/или сравнение для отсортированных множеств). - Queue.add(E element) - добавление в очередь. В отличие от
offer, бросаетIllegalStateExceptionпри переполнении ограниченной очереди. - BigInteger.add(BigInteger val) - арифметическая операция сложения больших целых, возвращает новый
BigInteger. - AtomicInteger.addAndGet(int delta) и LongAdder.add(long x) - атомарные операции для многопоточной среды, возвращающие итоговое или не возвращающие значение в зависимости от API.
- Math.addExact(int x, int y) - сложение с контролем переполнения; при переполнении бросает
ArithmeticException.
Частые исключения и результаты:
UnsupportedOperationException- когда коллекция неизменяема (например, списки черезList.of(...)илиArrays.asList(...)у фиксированного размера).IndexOutOfBoundsException- дляList.add(index,...)при неверном индексе.IllegalStateException- дляQueue.addпри переполнении ограниченной очереди.NullPointerException- в некоторых реализациях коллекций, если разрешениеnullзапрещено (например,ConcurrentHashMapи некоторые другие структуры).
Таким образом, при работе с add важно ориентироваться на конкретный класс или интерфейс: сигнатуры, возвращаемое значение и возможные исключения могут существенно отличаться.
Короткие примеры использования
Добавление в ArrayList - возвращаемое значение у add(E) обычно true (имплементация изменяется).
import java.util.*;
class Ex1 {
public static void main(String[] args) {
List list = new ArrayList<>();
boolean r = list.add("one");
System.out.println(r);
System.out.println(list);
}
}
true [one]
Добавление в HashSet и попытка добавить дубликат - видно поведение возвращаемого значения.
import java.util.*;
class Ex2 {
public static void main(String[] args) {
Set s = new HashSet<>();
System.out.println(s.add("a"));
System.out.println(s.add("a"));
System.out.println(s);
}
}
true false [a]
Вставка по индексу в список. Метод возвращает void, после вызова список изменяется.
import java.util.*;
class Ex3 {
public static void main(String[] args) {
List l = new ArrayList<>();
l.add("x");
l.add(0, "y");
System.out.println(l);
}
}
[y, x]
Queue.add против offer: при переполнении ограниченной очереди add бросит исключение.
import java.util.concurrent.ArrayBlockingQueue;
class Ex4 {
public static void main(String[] args) {
ArrayBlockingQueue q = new ArrayBlockingQueue<>(1);
q.add(1);
System.out.println(q);
q.add(2); // вызовет IllegalStateException
}
}
[1] // Исключение: // Exception in thread "main" java.lang.IllegalStateException: Queue full
BigInteger.add - арифметика больших чисел возвращает новый объект.
import java.math.BigInteger;
class Ex5 {
public static void main(String[] args) {
BigInteger a = new BigInteger("12345678901234567890");
BigInteger b = new BigInteger("10");
System.out.println(a.add(b));
}
}
12345678901234567900
Math.addExact обнаруживает переполнение.
class Ex6 {
public static void main(String[] args) {
int x = Integer.MAX_VALUE;
System.out.println(x);
System.out.println(Math.addExact(x, 1));
}
}
2147483647 // Exception in thread "main" java.lang.ArithmeticException: integer overflow
Похожие методы в Java
- addAll(Collection) - массовое добавление элементов; предпочтительнее при переносе сразу нескольких элементов ради производительности и читаемости.
- put / putIfAbsent у
Map- для ассоциативных структур;Mapне имеетadd, поэтому для пар ключ-значение применяетсяput. - offer у очередей - похожа на
add, но при переполнении возвращаетfalseвместо исключения; предпочтительна для мягкой обработки переполнения. - append у
StringBuilder- добавление текстовых данных в строковый буфер; отличается по назначению от коллекций.
Выбор между ними определяется задачей: добавление множества элементов - addAll, работа с парами ключ-значение - put, безопасное добавление в очередь без исключений - offer.
Аналоги в других языках
- PHP:
array_push($arr, $val)- добавляет в конец массива. Результат возвращает новую длину массива.
<?
$arr = [1];
$r = array_push($arr, 2);
var_dump($r);
var_dump($arr);
?>
int(2)
array(2) { [0]=> int(1) [1]=> int(2) }
Array.prototype.push - добавляет элементы, возвращает новая длина массива.let a = [1];
let r = a.push(2);
console.log(r);
console.log(a);
2 [1, 2]
list.append(x) - добавление в конец, возвращает None; list.insert(i, x) - вставка по индексу; set.add(x) - добавление в множество, результат не возвращается.l = [1]
print(l.append(2))
print(l)
s = set()
print(s.add(1))
print(s)
None
[1, 2]
None
{1}
INSERT - добавление строк в таблицу. Различие: операция долговременная и влияет на хранимые данные, возвращает статус выполнения, иногда идентификатор вставленной строки.List<T>.Add(item) - добавляет и не возвращает значение; HashSet<T>.Add(item) возвращает bool (true если добавлен).using System;
using System.Collections.Generic;
class P{ static void Main(){ var l=new List(); l.Add(1); var s=new HashSet(); Console.WriteLine(s.Add(1)); Console.WriteLine(s.Add(1)); }}
True False
append(slice, elems...) - возвращает новый срез; семантика отличается от методов коллекций Java, так как срезы в Go являются значениями.package main
import "fmt"
func main(){ s:=[]int{1}
s=append(s,2)
fmt.Println(s) }
[1 2]
MutableList.add и MutableSet.add похожи на Java; у Kotlin также есть оператор += для коллекций (вызов add под капотом).Ключевое отличие между языками - возвращаемые значения и семантика ошибок: в Java некоторые реализации возвращают булево значение, в Python и C# методы для списка часто ничего не возвращают, в JavaScript и PHP возвращается новая длина.
Типичные ошибки при применении add
- Попытка изменить неизменяемую коллекцию: вызов
addу списков, созданных черезList.of(...)или у фиксированного списка изArrays.asList, приводит кUnsupportedOperationException. - Ошибка индекса при
List.add(index, element): неверный индекс вызываетIndexOutOfBoundsException. - Различие в возвращаемом значении: ожидание булевого результата от
List.add(index,...), хотя этот метод возвращаетvoid. - ConcurrentModificationException при изменении коллекции внутри итератора с использованием методов самой коллекции вместо итератора.
- Игнорирование поведения
Queue.addпри переполнении - ожиданиеfalse, тогда как бросается исключение; для безопасной обработки лучшеoffer.
Пример ConcurrentModificationException.
import java.util.*;
class Err1 {
public static void main(String[] args) {
List l = new ArrayList<>(Arrays.asList(1,2,3));
for (Integer x : l) {
if (x == 2) l.add(4); // изменение коллекции во время обхода
}
}
}
// Exception in thread "main" java.util.ConcurrentModificationException
Пример UnsupportedOperationException при попытке добавить в неизменяемый список.
import java.util.*;
class Err2 { public static void main(String[] args) {
List l = List.of("a","b");
l.add("c");
}}
// Exception in thread "main" java.lang.UnsupportedOperationException
Изменения и замечания по версиям Java
- Непосредственно сигнатуры
addв основных коллекциях остаются стабильными на протяжении многих версий Java. - Java 8 представила новые удобства в API параллельных структур (например,
LongAdderдля эффективного суммирования в многопоточности), что расширило спектр методов добавления для атомарных операций. - В Java 9 появились фабричные методы
List.of,Set.of,Map.of, создающие неизменяемые коллекции - попытка вызватьaddприведет кUnsupportedOperationException. Это изменение влияет на код, ожидающий модифицируемые коллекции. - В API арифметики для обнаружения переполнения добавлены
Math.addExactи аналогичные методы (в Java 8), что обеспечивает безопасную проверку при сложении примитивов.
Расширенные и нестандартные примеры
Атомарное добавление с использованием AtomicInteger.addAndGet в многопоточном контексте.
import java.util.concurrent.atomic.AtomicInteger;
class Adv1 {
public static void main(String[] args) throws Exception{
AtomicInteger ai = new AtomicInteger(0);
Thread t1 = new Thread(() -> { for(int i=0;i<1000;i++) ai.addAndGet(1); });
Thread t2 = new Thread(() -> { for(int i=0;i<1000;i++) ai.addAndGet(1); });
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(ai.get());
}
}
2000
Использование Math.addExact для обнаружения переполнения в вычислениях, где важна корректность результата.
class Adv2 { public static int safeSum(int a,int b){
return Math.addExact(a,b);
}
public static void main(String[] args){
try{ System.out.println(safeSum(Integer.MAX_VALUE, 10)); }
catch(RuntimeException e){ System.out.println(e.getClass().getSimpleName()); }
}}
ArithmeticException
TreeSet и нестандартный компаратор: пример, где сравнение влияет на возможность добавления элементов (различие equals и compare может привести к неожиданным результатам).
import java.util.*;
class Adv3 {
public static void main(String[] args) {
Comparator cmp = (a,b) -> Integer.compare(a.length(), b.length());
SortedSet ts = new TreeSet<>(cmp);
ts.add("one");
System.out.println(ts.add("two")); // length 3 -> считаются равными по компаратору
System.out.println(ts);
}
}
false [one]
Стратегия добавления большого количества элементов: addAll часто эффективнее многократных add из-за внутренних оптимизаций у конкретных реализаций (например, резервирование места в ArrayList).
import java.util.*;
class Adv4 { public static void main(String[] args){
List target = new ArrayList<>();
List source = new ArrayList<>();
for(int i=0;i<10000;i++) source.add(i);
target.addAll(source);
System.out.println(target.size());
}}
10000
Создание собственной коллекции с контролируемым поведением add - пример переопределения, когда требуется валидация или фильтрация перед добавлением.
import java.util.*;
class ValidatingList extends ArrayList {
@Override
public boolean add(E e) {
if (e == null) throw new NullPointerException("null not allowed");
return super.add(e);
}
}
class Adv5 { public static void main(String[] args){
ValidatingList vl = new ValidatingList<>();
vl.add("ok");
System.out.println(vl);
}}
[ok]