
- •Структуры данных в картинках
- •ArrayList (список)
- •LinkedList (двунаправленный список)
- •HashSet (смотреть HashMap)
- •LinkedHashSet (смотреть LinkedHashMap)
- •Создание объекта
- •Создание объекта
- •Добавление элементов
- •Удаление элементов
- •Итераторы
- •Устаревшие коллекции
- •Вопросы:
- •Расскажите о ArrayList или LinkedList. Чем они отличаются?
Создание объекта
Map<Integer, String> linkedHashMap = new LinkedHashMap<Integer, String>();
Новоявленный объект linkedHashMap, содержит ряд свойств:
table - Массив типа table Entry[], который является хранилищем ссылок на списки (цепочки) значений; Entry<K,V> implements Map.Entry<K,V>
loadFactor – Коэффициент загрузки. Значение по умолчанию 0.75
threshold – Предельное количество элементов, при достижении которого, размер хэш-таблицы увеличивается вдвое. Формула: (capacity*loadFactor);
capacity – 16 элементов (по умолчанию), формула: (2^(4+n))
size – текущее количество элементов
Два доп. свойства:
header – голова двусвязного списка (при инициализации указывает сам на себя)
accessOrder – указывает каким образом будет осуществляться доступ к элементам при использовании итератора. При значении true — по порядку последнего доступа. При значении false (по умолчанию) доступ осуществляется в том порядке, в каком элементы были вставлены.
А у Entry добавляется два поля: after и before.
Добавление элементов
linkedHashMap.put(1, "obj1");
Сначала ключ проверяется на равенство null (запись в table[0])
Далее генерируется хэш на основе ключа
Определяется позиция в массиве (список), куда будет помещен элемент.
В этом списке ключ элемента сравнивается с ключами элементов списка
добавления нового элемента (если нет совпадений)
переопределение ссылок двусвязного списка
linkedHashMap.put(38, "obj38");
p.s. Обращаю ваше внимание, что в случае повторной вставки элемента (элемент с таким ключом уже существует) порядок доступа к элементам не изменится.
accessOrder = true
При вызове get() или put(), элемент будет помещен в конец списка. Т.е. элемент, к которому дольше всего не обращались (get() / put()) будет первым в списке.
put(1, "obj1"); // становится первым и последним в списке (after & before)
put(15, "obj15"); // стает последним
put(4, "obj4"); // стает последним
put(38, "obj38"); // стает последним
linkedHashMap.get(1); // стает последним (before)
Удаление элементов
linkedhashmap.remove(15);
remove(Object key)
Размер Entry table[] не уменьшается, решение – пересоздать Мар-у.
p.s. У HashMap есть такая же «проблема» как и у ArrayList — при удалении элементов размер массива table[] не уменьшается. И если в ArrayList предусмотрен метод trimToSize(), то в LinkedHashMap таких методов нет (хотя, как сказал один мой коллега — "А может оно и не надо?").
Итераторы
LinkedHashMap, как и HashMap имеет встроенные итераторы, такие, что вы можете получить список всех ключей keySet(), всех значений values() или же все пары ключ/значение entrySet(). Ниже представлены некоторые варианты для перебора элементов:
// 1.
for (Map.Entry<String, String> entry: hashmap.entrySet())
System.out.println(entry.getKey() + " = " + entry.getValue());
// 2.
for (String key: hashmap.keySet())
System.out.println(hashmap.get(key));
// 3.
Iterator<Map.Entry<String, String>> itr = hashmap.entrySet().iterator();
while (itr.hasNext())
System.out.println(itr.next());
p.s. Стоит помнить, что если в ходе работы итератора HashMap был изменен (без использования собственным методов итератора), то результат перебора элементов будет непредсказуемым.
p.s. Ну и не забывайте про fail-fast. Если начали перебор элементов — не изменяйте содержимое или заранее позаботьтесь о синхронизации (поменяв содержимое будет изменен порядок элементов).
Summary:
Свойства:
Не синхронизирован
Упорядочен (в порядке добавления / в порядке доступа к элементам)
Без дублирования ключей элементов (value могут быть одинаковы)
Не отсортирован
Позволяет хранить любые значения в том числе и null
Преимущества:
Добавление и выборка элемента выполняется за время O(1 + loadFactor), максимум может быть O(n), если все элементы находятся в одной цепочке.
Быстрый доступ к элементам (по хэшу) за время O(1);
время выполнения contains() = O(1 + loadFactor)
Недостатки:
Добавление и выборка элемента выполняется за время O(1 + loadFactor), максимум может быть O(n), если все элементы находятся в одной цепочке.
Много времени занимает перераспределение дерева.
table Entry[] не уменьшается в размере (нет trimToSize()), после удаления элементов
TreeMap
TreeMap - расширяет класс AbstractMap и реализует интерфейс NavigatebleMap. Он создает коллекцию, которая для хранения элементов применяет дерево. Объекты сохраняются в отсортированном порядке по возрастанию. Время доступа и извлечения элементов достаточно мало, что делает класс TreeMap блестящим выбором для хранения больших объемов отсортированной информации, которая должна быть быстро найдена. TreeMap http://www.quizful.net/post/Java-TreeMap.
WeakHashMap
WeakHashMap - коллекция, использующая слабые ссылки для ключей (а не значений). Слабая ссылка (англ. weak reference) — специфический вид ссылок на динамически создаваемые объекты в системах со сборкой мусора. Отличается от обычных ссылок тем, что не учитывается сборщиком мусора при выявлении объектов, подлежащих удалению. Ссылки, не являющиеся слабыми, также иногда именуют «сильными». http://ru.wikipedia.org/wiki/Слабая_ссылка.