Коллекции в Java в основном сосредоточены в двух частях: одна находится в пакете java.util, а другая — в java.util.concurrent. Последняя основана на первой и определяет некоторые коллекции, реализующие функции синхронизации.
Эта статья в основном посвящена различным объектам коллекций в java.util. Объекты коллекций в Java можно условно разделить на три категории: список, набор и карта. Соответствующая UML-диаграмма выглядит следующим образом (включая большинство объектов коллекций в java.util):
Обзор коллекции
И List, и Set в коллекциях Java происходят из Collection. Это хорошая отправная точка для изучения коллекций. Он включает в себя операции, которые обычно требуются в коллекциях.
Добавить элементы: add/addAll
Очистить коллекцию: очистить
Удалить элементы: удалить/удалить все
Определите, содержит ли коллекция элемент: contains/containsAll
Определите, пуста ли коллекция: isEmpty
Подсчитать количество элементов в коллекции: размер
Преобразовать коллекцию в массив: toArray
Получить итератор: итератор
Давайте рассмотрим простой пример. Следующий код вернет коллекцию, элементами которой являются случайно сгенерированные целые числа:
возврат сбора;
}
1) Используйте итераторы для перемещения по коллекции. Как упоминалось выше при описании интерфейса Collection, все коллекции будут иметь итератор, который мы можем использовать для обхода коллекции.
Список в Java — это эффективное расширение массива. Это структура, которая может содержать элементы любого типа, если не используются дженерики. Если дженерики используются, он может содержать только элементы типа, указанного дженериками. По сравнению с массивами емкость List можно динамически расширять.
Элементы в списке могут повторяться, а элементы внутри являются «упорядоченными». «Упорядоченный» здесь не означает сортировку, а означает, что мы можем указать положение элемента в коллекции.
Обычно используемые объекты коллекций в списке включают в себя: ArrayList, Vector и LinkedList, первые два хранятся на основе массивов, а последние — на основе связанных списков. Среди них Vector является потокобезопасным, а два других — нет.
Список может содержать значение NULL, даже если используются дженерики.
ArrayList может быть наиболее часто используемым объектом коллекции. В приведенном выше примере кода мы также используем его для создания экземпляра объекта Collection, поэтому мы не будем здесь вдаваться в подробности.
Вектор
Пример вектора выглядит следующим образом. Сначала мы посмотрим, как генерировать и выводить вектор:
[9, 29, 32, 54, 12]
размер вектора равен 3
[29, 32, 54]
LinkedList использует связанные списки для хранения данных. Его пример кода выглядит следующим образом:
Вывод следующий:
нулевой
нулевой
нулевой
размер связанного списка равен 8
[100, 84, 19, 57, 68, 26, 27, 47]
Set похож на List, оба используются для хранения одного элемента, а количество отдельных элементов неизвестно. Но Set не может содержать повторяющиеся элементы. Если в Set вставлены два одинаковых элемента, последний элемент не будет вставлен.
Набор можно условно разделить на две категории: несортированный набор и отсортированный набор. Несортированный набор включает в себя HashSet и LinkedHashSet, а отсортированный набор в основном относится к TreeSet. Среди них HashSet и LinkedHashSet могут содержать значение null.
Хэшсет
HashSet — это коллекция, поддерживаемая хеш-таблицей, которая не является потокобезопасной.
Давайте посмотрим на следующий пример, который по сути такой же, как и первый пример с Vector:
для (int я = 0; я <3; я++)
{
set.add(новое целое число(100));
}
set.add(ноль);
System.out.println("Размер набора равен " + set.size());
System.out.println(набор);
}
классMyInteger
{
частное целочисленное значение;
public MyInteger (целое значение)
{
это.значение = значение;
}
публичная строка toString()
{
вернуть String.valueOf(значение);
}
общедоступный int hashCode()
{
возврат 1;
}
общедоступное логическое равенство (Object obj)
{
вернуть истину;
}
}
Ниже приводится соответствующий метод испытаний:
для (int я = 0; я <3; я++)
{
set.add(новый MyInteger(100));
}
System.out.println("размер набора равен " + set.size());
System.out.println(набор);
}
TreeSet — это набор, поддерживающий сортировку, а его родительский интерфейс — SortedSet.
Давайте сначала рассмотрим основные операции TreeSet:
Случайный r = новый Random();
для (int я = 0; я <5; я++)
{
set.add(new Integer(r.nextInt(100)));
}
System.out.println(набор);
System.out.println(set.first());
System.out.println(set.last());
System.out.println(set.descendingSet());
System.out.println(set.headSet(new Integer(50)));
System.out.println(set.tailSet(new Integer(50)));
System.out.println(set.subSet(30, 60));
System.out.println(set.floor(50));
System.out.println(set.ceiling(50));
}
[53, 49, 48, 42, 8]
[8, 42, 48, 49]
[53]
[42, 48, 49, 53]
Далее мы сначала переопределяем Integer:
общедоступный MyInteger2 (целое значение)
{
это.значение = значение;
}
public int CompareTo (Объект arg0)
{
MyInteger2 temp = (MyInteger2)arg0;
если (temp == null) вернуть -1;
если (темп.значение > это.значение)
{
возврат 1;
}
иначе, если (temp.value < this.value)
{
вернуть -1;
}
вернуть 0;
}
общедоступное логическое равенство (Object obj)
{
вернуть сравнениеTo(obj) == 0;
}
публичная строка toString()
{
вернуть String.valueOf(значение);
}
}
Карта хранит «пары ключ-значение». Подобно Set, в Java существует два типа карт: сортированные и несортированные включают HashMap, Hashtable и LinkedHashMap, а сортированные включают TreeMap.
Несортированная карта
И HashMap, и Hashtable хранятся в виде Hash-таблиц. HashMap не является потокобезопасным, но Hashtable является поточно-ориентированным. Мы можем рассматривать HashMap как «упрощенную» версию Hashtable.
HashMap может хранить значение null как для ключа, так и для значения. Хэш-таблица не может хранить значение null.
Независимо от HashMap или Hashtable, если мы посмотрим на его конструктор, мы обнаружим, что он может иметь два параметра: InitialCapacity и loadFactor. По умолчанию InitialCapacity равен 16, а loadFactor равен 0,75. Это связано с количеством элементов, которые могут быть сохранены в хеш-таблице. Когда количество элементов превышает начальную емкость*loadFactor, будет запущен метод повторного хеширования для расширения хеш-таблицы. Если нам нужно вставить в него слишком много элементов, нам нужно соответствующим образом настроить эти два параметра.
Давайте сначала посмотрим на пример HashMap:
map.put(новое целое число(1), "а");
map.put(новое целое число(2), "b");
map.put(новое целое число(3), "c");
System.out.println(карта);
System.out.println(map.entrySet());
System.out.println(map.keySet());
System.out.println(map.values());
}
Map.put(ноль, ноль);
Map.put(ноль, ноль);
map.put(новое целое число(4), ноль);
map.put(новое целое число(5), ноль);
System.out.println(карта);
System.out.println(map.entrySet());
System.out.println(map.keySet());
System.out.println(map.values());
}
table.put(new Integer(1), "a");
table.put(new Integer(2), "b");
table.put(новое целое число(3), "c");
System.out.println(таблица);
System.out.println(table.entrySet());
System.out.println(table.keySet());
System.out.println(table.values());
}
частная статическая пустота hashTableTest2()
{
Таблица Map<Integer,String> = новая Hashtable<Integer, String>();
table.put(нуль, ноль);
table.put(нуль, ноль);
table.put(новое целое число(4), ноль);
table.put(новое целое число(5), ноль);
System.out.println(таблица);
System.out.println(table.entrySet());
System.out.println(table.keySet());
System.out.println(table.values());
}
Карта сортировки в основном относится к TreeMap, временная сложность которой составляет O(log(n)) при добавлении, удалении и поиске элементов. Это не потокобезопасно.
Его характеристики очень похожи на TreeSet, поэтому я не буду здесь вдаваться в подробности.