Коллекции – это контейнеры, в которых можно хранить условно однотипные* объекты. Отличия от массивов:
Предоставляют значительно больше возможностей для хранения и управления элементами, чем массивы
Имеют возможность добавления и удаления элементов с динамическим изменением размера коллекции
Могут хранить только объекты, но не примитивные типы (однако, можно использовать классы-обертки)
Работают медленнее, чем массивы
*Элементы коллекции должны иметь одинаковый базовый класс
Основные типы коллекций
Java.util.List – список (хранит элементы в порядке вставки, доступ к ним осуществляется по индексу)
java.util.Set – множество (каждый элемент встречается не более одного раза)
java.util.Queue – очередь (выдает элементы в порядке вставки элементов в очередь, FIFO – First In, First Out)
java.util.Map – ассоциативный массив (словарь, набор пар «ключ-значение»)
Иерархия классов коллекций
Базовый интерфейс Collection
Основные операции:
int size()
boolean isEmpty()
boolean contains(Object o)
boolean add(E e)
boolean remove(Object o)
void clear()
Iterator
Итератор используется для того, чтобы получить доступ к элементам коллекции. Итератор можно получить из любой коллекции, вызвав у нее метод iterator().
Iterator содержит следующие методы:
boolean hasNext()
E next()
void remove()
Однако, в большинстве случаев удобнее пользоваться циклом foreach для перебора элементов коллекции. Итератор стоит использовать тогда, когда нужно удалить какой-либо элемент. Если попробовать удалить его в цикле, программа, скорее всего, выдаст ошибку и аварийно завершит работу.
Java.util.List
List
Хранит элементы в порядке вставки
Доступ к элементам осуществляется по индексу
Основные операции:
E get(int index)
E set(int index, E element)
void add(int index, E element)
E remove(int index)
int indexOf(Object o)
int lastIndexOf(Object o)
List subList(int fromIndex, int toIndex)
Подклассы:
ArrayList
LinkedList
Vector
ArrayList
ArrayList – это список, реализованный на основе массива.
Преимущества:
Возможность доступа к произвольному элементу по индексу за постоянное время (так как это массив),
Минимум затрат ресурсов при хранении такого списка
Вставка в конец списка и удаление производится за постоянное время, если размер списка заранее определен при помощи метода ensureCapacity(), либо при помощи передачи резервируемого объема памяти в конструктор.
Недостатки:
при вставке n+1 элемента в список размера n приходится перезаписывать массив, что замедляет работу программы
при вставке/удалении элемента в середине списка происходит перезапись всех элементов размещенных «правее» в списке на одну позицию влево
при удалении элементов размер массива не уменьшается, до явного вызова метода trimToSize()
Пример ArrayList
ArrayList words = new ArrayList();
words.add(“one”);
words.set(0, “two”);
words.add(0, “three”);
words.remove(1);
// В итоге в списке останется элемент с индексом 0 и значением “three”
LinkedList
LinkedList – это двусвязный список, основанный на работе с объектами и ссылками между ними (каждый объект хранит ссылки на предыдущее и следующее значения).
Преимущества:
Может выполнять вставку/удаление элементов в списке за постоянное время
Доступ к первому и последнему элементу списка также осуществляется за постоянное время
Недостатки:
Доступ к произвольному элементу имеет линейную трудоемкость
В целом LinkedList проигрывает ArrayList и по потребляемой памяти и по скорости выполнения операций. LinkedList предпочтительно применять, когда происходит активная работа (вставка/удаление) с серединой списка или в случаях, когда необходимо гарантированное время добавления элемента в список.
Список можно отсортировать при помощи метода Collections.sort(), который имеет два перегруженных варианта:
sort(List list)
sort(List list, Comparator super T> c)
Первый вариант метода сортирует строки и числа по возрастанию. Для того, чтобы задать свой способ сортировки или отсортировать объекты созданных классов, необходимо реализовать интерфейс Comparable и передать его методу sort(). Пример:
Collections.sort(list, new Comparator() {
public int compare(String o1, String o2) {
Integer i1 = Integer.parseInt(o1);
Integer i2 = Integer.parseInt(o2);
return (i1 > i2 ? -1 : (i1 == i2 ? 0 : 1));
}
});
java.util.Set
Set
Множество – это контейнер, в котором каждый элемент хранится только в одном экземпляре. Такой вид коллекции часто используется для проверки принадлежности объекта заданному множеству. Следовательно, важнейшей операции является операция поиска, поэтому на практике обычно выбирается множество типа HashSet, оптимизированная для быстрого поиска. Особенности:
Каждый элемент встречается не более одного раза (гарантирует, что при добавлении элементов, дубликаты не появятся)
Не добавляет новых операций к тем, что есть в интерфейсе Collection
HashSet и LinkedHashSet
Особенности HashSet:
Реализация множества на основе хеш-таблицы
Порядок обхода элементов непредсказуем
LinkedHashSet аналогичен HashSet. Отличие заключается в том, что порядок обхода элементов определяется порядком вставки
Set figures = new HashSet();
Set cars = new LinkedHashSet();
TreeSet
Особенности:
Реализация множества на основе дерева поиска
Элементы хранятся отсортированными
Хранить можно числа и строки
SortedSet words = new TreeSet();
words.add(“bbb”);
words.add(“aaa”);
words.add(“ccc”);
words.headSet(“bbb”).clear();
Удаление дубликатов из коллекции
List animals = new ArrayList();
animals.add("Cat");
animals.add("Dog");
animals.add("Cat");
animals.add("Hamster");
Set tmpSet = new HashSet(animals);
animals = new ArrayList(tmpSet);
System.out.print (animals);
// Output
[Cat, Dog, Hamster]
Сортировка множеств
Отсортировать множество можно двумя способами:
Изначально использовать множество TreeSet (при этом конструктору можно передать собственную реализацию интерфейса Comparator)
Создать новое множество TreeSet и передать ему в конструктор существующее множество. Пример:
Queue (очередь) обычно представляет собой контейнер, работающий по принципу Last In, First Out (LIFO). Иначе говоря, элементы заносятся в очередь с одного «конца» и извлекаются с другого в порядке их поступления. Очереди часто используются для реализации надежной передачи объектов между разными областями программы. Интерфейс Queue реализуется в классах LinkedList и PriorityQueue.
Основные операции представлены в таблице:
Выбрасывает исключение
Возвращает значение
Вставка элемента
add(e)
offer(e)
Удаление элемента
remove()
poll()
Получение элемента
element()
peek()
Пример Queue
Queue qc = new LinkedList();
for (char c : "Dinosaurus".toCharArray())
qc.offer(c);
while(qc.peek() != null)
System.out.print(qc.remove()+" ");
// Output: D i n o s a u r u s
Сделать задания 1, 2, 3
java.util.Map
Map
Карта отображает одни объекты на другие. По сути это ассоциативный массив, в котором доступ к объекту можно получить зная его ключ (набор пар «ключ-значение»). Map – это интерфейс и он НЕ реализует интерфейс collection, в отличие от всех остальных типов коллекций (см схему на 4 слайде). Для того, чтобы начать работать с картной, необходимо создать объект одного из классов:
HashMap, LinkedHashMap, TreeMap или HashTable.
Основные операции, описанные в Map
int size()
boolean isEmpty()
V get(Object key)
V put(K key, V value)
V remove(Object key)
boolean containsKey(Object key)
boolean containsValue(Object key)
Set keySet()
Collection values()
Set> entrySet()
HashMap и LinkedHashMap
Особенности:
Реализация ассоциативного массива на основе хеш-таблицы
Порядок обхода элементов непредсказуем (HashMap) либо обусловлен порядком вставки (LinkedHashMap)
Map planets = new HashMap();
// Autoboxing: автоматическая упаковка примитивных типов в
// классы-обертки (в данном случае int -> Integer)