Коллекции в Java

Аналоги списков (list), множеств (set) в python.

Коллекция в Java — набор из нескольких объектов. В коллекциях пока можно хранить только объектные типы, т.е. коллекцию int пока не сделать. У коллекции можно узнать размер (метод size()), ее можно перечислить:

for (String s : коллекция строк) {
    действие с элементом коллекции s
}

Еще можно проверить на пустоту (isEmpty()), добавить или удалить элементы (add(), remove()). Есть другие методы

Те виды коллекций, которые нам нужны, можно поделить на два вида:

Коллекции описываются классом Collection, cписки: List, множества: класс Set. Классы коллекций надо указывать с угловыми скобками, в них указывается тип элементов коллекции. Например, List<String> — это список строк. Set<Integer> — это множество чисел. (Integer см. позже). Java разрешает писать без угловых скобок, но это не рекомендуется: List s = ... (так не делаем). Их можно не писать только из исторических соображений. Если вы их забудете, получите ошибку или предупреждение о “raw type”.

Примеры:

//создали список из трёх элементов.
List<String> s = List.of("abc", "xyz", "pqr");
//часто можно опускать содержимое угловых скобок, если оно очевидно:
List<> s = List.of("abc", "xyz", "pqr"); //догадается до List<String>

System.out.println(s); // в отличие от массивов распечатка коллекций красивая

//метод contains, общий для всех коллекций:
System.out.println(s.contains("abc")); // true

Самый простой способ создания списка — это List.of(), но таким образом создаётся неизменяемый список… Любая операция типа add по добавлению элемента приводит к ошибке времени выполнения.

Чтобы создать свой список, нужен класс ArrayList, это наследник List. Это реализация списка с помощью массива. Есть еще LinkedList, он основан на структуре данных “связанный список”. При создании списка нужно явно указывать, какой список необходим:

//вызов конструктора, создание списка, конкретно ArrayList
List<String> s = new ArrayList<>(); //здесь справа убираем <String>
 // List<String> s = new List() — невозможно, 

s.add("abc");
s.add("xyz");
s.add("pqr");

System.out.println(s); // список из трех слов
System.out.println(s.size()); // узнаем длину, получаем 3

В списках есть дополнительные методы, которых нет в коллекциях, например, get:

List<String> s = List.of("abc", "xyz", "pqr");
System.out.println(s.get(0)); // abc
System.out.println(s.get(1)); // xyz
s.remove(1); // удалить элемент по первому индексу
System.out.println(s); // "abc", "pqr"

Создание множества:

//неизменяемое множество
Set<Stirng> set1 = Set.of("abc", "xyz", "pqr");

//изменяемые множества
Set<String> set2 = new HashSet<>();
Set<String> set3 = new LinkedHashSet<>();
Set<String> set4 = new TreeSet<>();

Хранение примитивных типов в коллекциях

Вообще, List<int> не бывает (пока). У каждого примитивного типа есть класс-обертка:

Эти типы служат двум целям

Integer i = new Integer(42); // 42 внутри объекта
System.out.println(i); //42
System.out.println(i.intValue()); //42 как int

Скоро в Java запретят делать new Integer. На самом деле, в Java работает автоматическое заворачивание (auto boxing) и автоматическое разворачивание (auto unboxing):

Integer i = 1042; // тип справа int, автоматически делает new Integer(1042);. Autoboxing
int ii = i; // содержимое объекта i автоматически достаётся в ii. Autounboxing

Аналогично это работает в коллекциях и везде, где Integer должно превратиться в int и наоборот:

List<Integer> i = List.of(10, 20, 30);

List<Integer> a = new ArrayList<>();
a.add(42); // auto boxing
a.add(123); // auto boxing

int z = a.get(0); //возвращается Integer, auto unboxing

Ожидаются Integer, получены int, они автоматически завернутся в Integer.

Замечание. В явном виде класс Integer и другие классы обертки создаются/используются редко. Обычно только в угловых скобках (типовой параметр).

Замечание о внимательности. Autoboxing всегда отрабатывает без ошибок. А вот autounboxing иногда может завершиться ошибкой. Если значение null, оно не развернется:

Integer z = null;
int a = z; // возникнет ошибка при разворачивании (NullPointerException)

Замечание. Замена элемента в списке:

List<String> s = new ArrayList<>();

s.add("abc");
s.add("xyz");
s.add("pqr");

s.set(1, "xxyyzz"); // заменяем значение по индексу 1

В Python было бы s[1] = "xxyyzz".