Для получения печатного представления массива необходимо использовать метод Arrays.toString, но контейнеры отлично выводятся и без посторонней помощи. Следующий пример демонстрирует использование основных типов контейнеров:
</spoiler> Как уже было упомянуто, в библиотеке контейнеров Java существует две основные категории, различающиеся прежде всего тем, сколько в одной ячейке контейнера «помещается» элементов. Коллекции (Collection) содержат только один элемент в каждой ячейке. К этой категории относятся список (List), где в определенной последовательности хранится группа элементов, множество (Set), в которое можно добавлять только по одному элементу определенного типа, и очередь (Queue). В контейнерах Map (карта) хранятся два объекта: ключ и связанное с ним значение. Из выходных данных программы видно, что вывод по умолчанию (обеспечиваемый методом toString() каждого контейнера) дает вполне приличные результаты. Содержимое Collection выводится в квадратных скобках, с разделением элементов запятыми. Содержимое Map заключается в фигурные скобки, ключи и значения разделяются знаком равенства (ключи слева, значения справа). Контейнеры ArrayList и LinkedList принадлежат к семейству List, и из выходных данных видно, что элементы в них хранятся в порядке вставки. Они различаются не только скоростью выполнения тех или иных операций, но и тем, что LinkedList содержит больше операций, чем ArrayList. HashSet, TreeSet и LinkedHashSet относятся к семейству Set. Из выходных данных видно, что в множествах Set каждый элемент хранится только в одном экземпляре, а разные реализации Set используют разный порядок хранения элементов. В HashSet порядок элементов определяется по довольно сложному алгоритму — пока достаточно знать, что этот алгоритм обеспечивает минимальное время выборки элементов, но порядок следования элементов на первый взгляд выглядит хаотично. Если порядок хранения для вас важен, используйте контейнер TreeSet, в котором объекты хранятся отсортированными по возрастанию в порядке сравнения, или LinkedHashSet с хранением элементов в порядке добавления. Карта (Map) позволяет искать объекты по ключу, как несложная база данных. Объект, ассоциированный с ключом, называется значением. (Карты также называют ассоциативными массивами.) В нашем примере используются три основные разновидности Map: HashMap, TreeMap и LinkedHashMap. Как и HashSet, HashMap обеспечивает максимальную скорость выборки, а порядок хранения его элементов не очевиден. TreeMap хранит ключи отсортированными по возрастанию, a LinkedHashMap хранит ключи в порядке вставки, но обеспечивает скорость поиска HashMap.
List
Контейнеры List гарантируют определенный порядок следования элементов. Интерфейс List дополняет Collection несколькими методами, обеспечивающими вставку и удаление элементов в середине списка. Существует две основные разновидности List:
· Базовый контейнер ArrayList, оптимизированный для произвольного доступа к элементам, но с относительно медленнными операциями вставки (удаления) элементов в середине списка.
· Контейнер LinkedList, оптимизированный для последовательного доступа, с быстрыми операциями вставки (удаления) в середине списка; Произвольный доступ к элементам LinkedList выполняется относительно медленно, но по широте возможностей он превосходитArrayList.
В следующем примере используется библиотека typenfo.pets из главы «Информация о типе». Она содержит иерархию классов домашних животных Pet, а также ряд вспомогательных средств для случайного построения объектов Pet. Пока достаточно знать, что (1) библиотека содержит класс Pet и производные типы, и (2) статический метод Pets.arrayList() возвращает контейнер ArrayList, заполненный случайно выбранными объектами Pet.
</spoiler> Строки вывода пронумерованы, чтобы вам было удобнее связывать результат с исходным кодом. В первой строке выводится исходный контейнер List с объектами Pets. В отличие от массивов, List поддерживает добавление и удаление элементов с изменением размеров списка. Результат добавления Hamster виден в строке 2: объект появляется в конце списка.
Метод contains() проверяет, присутствует ли объект в списке. Чтобы удалить объект, передайте ссылку на него методу remove(). Кроме того, при наличии ссылки на объект можно узнать его индекс в списке при помощи метода indexOf(), как показано в строке 4.
При проверке вхождения элемента в List, проверке индекса элемента и удаления элемента из List по ссылке используется метод equals() (из корневого класса Object). Все объекты Pet считаются уникальными, поэтому несмотря на присутствие двух объектов Cymric в списке, если я создам новый объект Cymric и передам его indexOf(), результат будет равен -1 (элемент не найден), а вызов remove() вернет false. Для других классов метод equals() может быть определен иначе — например, объекты String считаются равными в случае совпадения содержимого.
В строках 7 и 8 из List успешно удаляется заданный объект. Строка 9 и предшествующий ей код демонстрируют вставку элемента в середину списка. Метод subList() позволяет легко создать «срез» из подмножества элементов списка; естественно, при передаче его методуcontainsAll() большего списка будет получен истинный результат. Вызовы Collections.sort() и Collections.shuffle() для sub не влияют на результат вызова containsAll().
Метод retainAll() фактически выполняет операцию «пересечения множеств», то есть определения всех элементов сору, которые также присутствуют в sub. И снова поведение метода зависит от реализации equals().
В строке 14 представлен результат удаления элемента по индексу — это проще, чем удаление по ссылке на объект, потому что вам не придется беспокоиться о поведении equals(). Работа метода removeAll() также зависит от equals(). Как подсказывает название, метод удаляет из List все объекты, входящие в List-аргумент.
Название метода set() выбрано неудачно, потому что оно совпадает с именем класса Set — возможно, лучше было бы назвать метод «replace», потому что он заменяет элемент с заданным индексом (первый аргумент) вторым аргументом.
В строке вывода 17 показано, что для List существует перегруженный метод addAll(), вставляющий новый список в середину исходного списка (вместо простого добавления в конец методом addAll(), унаследованным от Collection).
В строках 18-20 представлен результат вызова методов isEmpty() и clear(). Строки 22 и 23 демонстрируют, что любой объект Collection можно преобразовать в массив с использованием toArray().