Entry java что это
Использование Java-класса Map.Entry
1. Обзор
2. Оптимизация итерации Карты
Предположим, что у нас есть карта названий книг с именем автора в качестве ключа:
Давайте сравним два метода получения всех ключей и значений с нашей карты.
2.1. Использование Map.keySet
Во-первых, рассмотрим следующее:
Если нам нужны только ключи на карте, keySet – хороший вариант. Однако есть более быстрый способ получить как ключи, так и значения.
2.2. Использование Map.entrySet Вместо
Давайте перепишем нашу итерацию, чтобы использовать entrySet :
3. Работа С Кортежами
3.1. Создание кортежа
Во-первых, рассмотрим класс Book :
Далее давайте создадим кортеж Map.Entry с ISBN в качестве ключа и объектом Book в качестве значения:
Наконец, давайте создадим экземпляр нашего кортежа с помощью AbstractMap.SimpleEntry :
3.2. Создание упорядоченного списка кортежей
При работе с кортежами часто полезно иметь их в виде упорядоченного списка.
Сначала мы определим наш список кортежей:
Во-вторых, давайте добавим несколько записей в наш список:
3.3. Сравнение С Картой
Во-вторых, мы пройдемся по нашему списку, отобразив все ключи и значения:
Наконец, давайте посмотрим на результат:
3.4. Списки объектов ввода
Следует отметить, что цель Entry не состоит в том, чтобы действовать как общий кортеж. Библиотечные классы часто предоставляют общую пару класс для этой цели.
Однако мы можем обнаружить, что нам необходимо временно работать со списками записей при подготовке данных для Карты или извлечении данных из одного из них.
4. Заключение
В этой статье мы рассмотрели Map.entrySet как альтернативу перебору ключей карты.
Затем мы рассмотрели, как Map.Entry можно использовать в качестве кортежа.
Entry java что это
В интерфейсе java.util.Map параметризуются два типа, это ключ и значение.
Объявление java.util.Map выглядит как:
При этом стоит отметить, что не может быть повторяющихся ключей, что следует из названия и смысла Map : каждому ключу соответствует значение.
Вопрос:
Ответ:
Класс java.util.Dictionary является полностью абтрактным, без какого-либо состояния.
Но благодаря WORA в Java просто так ничего не меняют и не удаляют, поэтому старые классы остались, а новую иерархию начали строить с интерфейсов.
Основные методы, которые предоставляет интерфейс java.util.Map :
Это значит, что все реализации интерфейса java.util.Map позволяют доставать, добавлять и удалять элементы по ключам, а также предоставлять множество ключей и коллекцию хранимых значений.
Как уже было сказано выше, Map это набор пар ключ-значение.
Объявление java.util.Map#Entry выглядит как:
И предоставляет методы, позволяющие получить/установить ключ и значение.
Помимо всего прочего предоставляются также компараторы для сравнения пар по ключу и значению.
Объявление выглядит следующим образом:
Объявление выглядит следующим образом:
Иерархия классов выглядит следующим образом:
Абстрактный класс java.util.AbstractMap предоставляет заготовку для последующих реализаций.
Что говорит о том, что операция не поддерживется и ее надо либо не использовать, либо переопределить метод.
Наиболее известные реализации java.util.Map :
Когда и какую реализацию выбрать?
Если порядок хранения элементов не важен, то выбор java.util.HashMap более чем оправдан.
Помните, что java.util.TreeMap не поддерживает работу с null ключами.
Структура данных | Производительность (basic ops) | Память | Отсортированность элементов | Работа с null |
---|---|---|---|---|
Treemap | O(log(N)) | Без издержек | В естественном порядке | Недопустимы null ключи, без ограничений на null значения |
HashMap | O(1) | С издержками | Неотсортирован | Допустим null ключ, без ограничений на null значения |
Linked HashMap | O(1) (но медленнее HashMap) | Также как и в HashMap | В порядке добавления | Допустим null ключ, без ограничений на null значения |
При этом следует помнить, что порядок гарантируеутся не всеми реализациями, как например в примере выше.
Стоит помнить, что, как и в случае с итерированием сипсков, если в ходе работы итератора структура данных была изменена (без использования методов итератора), то будет выброшено исключение:
Избежать этого можно удаляя элемент с помощью итератора, с которым происходит работа:
Иерархия Map
— Ну и напоследок расскажу о Map.
Map, как ты знаешь, хранит набор пар «ключ-значение». Ключи должны быть уникальны, значения – любые. Если ты добавляешь в Map пару ключ-значение, а такой ключ в коллекции уже есть, то старое значение заменится на новое. Т.е. ключ – это что-то вроде уникального индекса, который может быть любым объектом.
Как только название Map ни переводится на русский язык. Версий уже существует, наверное, десятка полтора. Самые распространённые – это Словарь, Карта, Отображение, …
Название Map – это математический термин, который обозначает набор (множество) пар (x,y), где каждому уникальному x соответствует какой-то y.
Программисты очень любят Map, поэтому у нас тут аж 4 различных коллекции, реализующих интерфейс java Map:
Вот тебе ее простенькая структура наследования:
Желтым отмечено, что Entry – это вложенный интерфейс в интерфейсе Map.
Entry был добавлен, чтобы описать именно пару элементов как одну сущность.
Вот какие методы есть у Map :
Методы | Описание |
---|---|
int size() | Возвращает количество пар в map. |
boolean isEmpty() | Проверяет, пустой ли map. |
boolean containsKey(Object key) | Содержит ли map заданный ключ? |
boolean containsValue(Object value) | Содержит ли map заданное значение? |
V get(Object key) | Возвращает значение по ключу. |
V put(K key, V value) | Устанавливает новое значение ключу. Метод возвращает старое значение или null |
putAll(Map m) | Добавляет пары из другого map. |
void clear() | Очищает map – удаляет все пары. |
Set keySet() | Возвращает Set из ключей. |
Collection values() | Возвращает коллекцию из значений. |
Set >entrySet() | Возвращает множество (Set) пар. |
K,V – это типы-параметры для ключей (Key) и значений(Value).
— Ну, с большинством методов я знаком, хотя работал только с некоторыми из них.
А что еще за Entry такой?
— Это класс, который описывает пару элементов. Методов у него немного:
Методы | Описание |
---|---|
K getKey() | Возвращает значение «ключа пары». |
V getValue() | Возвращает значение «значения пары». |
V setValue(V value) | Устанавливает новое значение «значения пары». |
Entry удобен тем, что ты можешь взять какую-то пару и передать ее в нужный метод, не передавая туда всю коллекцию map.
— Ну и пробегусь еще по реализациям Map.
Первая на очереди – это коллекция HashMap. Она использует хэш-таблицы для хранения элементов. Ключи и значения могут быть любых типов, а также могут быть null. Порядок элементов может меняться при изменении коллекции.
Элементы хранятся внутри HashMap в виде набора групп – корзин (bucket). В какую корзину попадет элемент — зависит от значения его hashCode().
Очень грубо говоря, элементы со значением хэш-кода от 1 до 100 попадают в первую корзину, со значением от 101 до 200 — во вторую, и т.д.
Смысл такого хранения в том, что при поиске/удалении можно отбрасывать ненужные корзины, и исключать все их элементы из рассмотрения.
— Есть очень хорошая статья по HashMap, советую почитать http://habrahabr.ru/post/128017/
Вторая коллекция – это LinkedHashMap. Основное ее отличие от HashMap – она дополнительно хранит элементы в виде связного списка. У обычной HashMap порядок элементов неопределён и, строго говоря, может меняться со временем. А у LinkedHashMap можно получить итератор и с помощью него перебрать все элементы в порядке их добавления в LinkedHashMap. Так же у LinkedHashMap есть итератор, который позволяет обойти все пары в порядке из последнего использования/активности.
Есть очень хорошая статья по LinkedHashMap, держи http://habrahabr.ru/post/129037/
Третья коллекция, о которой я бы хотела сегодня рассказать – это TreeMap.
TreeMap хранит свои элементы отсортированными по возрастанию. Это достигается благодаря тому, что TreeMap для их хранения использует сбалансированное красно-черное бинарное дерево.
Благодаря этому там очень низкое время вставки и поиска элементов. Этот класс – отличный выбор при использовании очень больших объемов данных.
Что я еще не рассказала?
— WeakHashMap, но мне Риша рассказывал про него пару дней назад.
— Ну, когда рассказывала про SoftReference, WeakReference и PhantomReference.
— Верю, учитывая, что ты все правильно назвал. Тогда иди отдыхай. Вечером увидимся.
Ответы на самые популярные вопросы об интерфейсе Map
0. Как перебрать все значения Map
1. Как конвертировать Map в List
2. Как отсортировать ключи мапы
Поместить Map.Entry в список и отсортировать его, используя Comparator.
В компараторе будем сравнивать исключительно ключи пар:
Если разобрался с лямбдами, эту запись можно существенно сократить:
И, конечно, все можно переписать, используя лямбды:
В отличие от первого способа, используя SortedMap, мы всегда будем хранить данные в отсортированном виде.
3. Как отсортировать значения мапы
4. В чем разница между HashMap, TreeMap, и Hashtable
Порядок элементов. HashMap и Hashtable не гарантируют, что элементы будут храниться в порядке добавления. Кроме того, они не гарантируют, что порядок элементов не будет меняться со временем. В свою очередь, TreeMap гарантирует хранение элементов в порядке добавления или же в соответствии с заданным компаратором.
Допустимые значения. HashMap позволяет иметь ключ и значение null, HashTable — нет. TreeMap может использовать значения null только если это позволяет компаратор. Без использования компаратора (при хранении пар в порядке добавления) значение null не допускается.
Синхронизация. Только HashTable синхронизирована, остальные — нет. Если к мапе не будут обращаться разные потоки, рекомендуется использовать HashMap вместо HashTable.
И общее сравнение реализаций:
HashMap | HashTable | TreeMap | |
---|---|---|---|
Упорядоченность элементов | нет | нет | да |
null в качестве значения | да | нет | да/нет |
Потокобезопасность | нет | да | нет |
Алгоритмическая сложность поиска элементов | O(1) | O(1) | O(log n) |
Структура данных под капотом | хэш-таблица | хэш-таблица | красно-чёрное дерево |
5. Как создать двунаправленную мапу
6. Как создать пустую Map
Обычная инициализация объекта:
Создание неизменяемой (immutable) пустой мапы:
Структуры данных в картинках. HashMap
Приветствую вас, хабрачитатели!
Продолжаю попытки визуализировать структуры данных в Java. В предыдущих сериях мы уже ознакомились с ArrayList и LinkedList, сегодня же рассмотрим HashMap.
HashMap — основан на хэш-таблицах, реализует интерфейс Map (что подразумевает хранение данных в виде пар ключ/значение). Ключи и значения могут быть любых типов, в том числе и null. Данная реализация не дает гарантий относительно порядка элементов с течением времени. Разрешение коллизий осуществляется с помощью метода цепочек.
Создание объекта
Вы можете указать свои емкость и коэффициент загрузки, используя конструкторы HashMap(capacity) и HashMap(capacity, loadFactor). Максимальная емкость, которую вы сможете установить, равна половине максимального значения int (1073741824).
Добавление элементов
Комментарий из исходников объясняет, каких результатов стоит ожидать — метод hash(key) гарантирует что полученные хэш-коды, будут иметь только ограниченное количество коллизий (примерно 8, при дефолтном значении коэффициента загрузки).
В моем случае, для ключа со значением »0» метод hashCode() вернул значение 48, в итоге:
При значении хэша 51 и размере таблице 16, мы получаем индекс в массиве:
Для того чтобы продемонстрировать, как заполняется HashMap, добавим еще несколько элементов.
Footprint
Object size: 376 bytes
Footprint
Object size: 496 bytes
Resize и Transfer
Когда массив table[] заполняется до предельного значения, его размер увеличивается вдвое и происходит перераспределение элементов. Как вы сами можете убедиться, ничего сложного в методах resize(capacity) и transfer(newTable) нет.
Метод transfer() перебирает все элементы текущего хранилища, пересчитывает их индексы (с учетом нового размера) и перераспределяет элементы по новому массиву.
Если в исходный hashmap добавить, скажем, еще 15 элементов, то в результате размер будет увеличен и распределение элементов изменится.
Удаление элементов
У HashMap есть такая же «проблема» как и у ArrayList — при удалении элементов размер массива table[] не уменьшается. И если в ArrayList предусмотрен метод trimToSize(), то в HashMap таких методов нет (хотя, как сказал один мой коллега — «А может оно и не надо?«).
Небольшой тест, для демонстрации того что написано выше. Исходный объект занимает 496 байт. Добавим, например, 150 элементов.
Теперь удалим те же 150 элементов, и снова замерим.
Как видно, размер даже близко не вернулся к исходному. Если есть желание/потребность исправить ситуацию, можно, например, воспользоваться конструктором HashMap(Map).
Итераторы
HashMap имеет встроенные итераторы, такие, что вы можете получить список всех ключей keySet(), всех значений values() или же все пары ключ/значение entrySet(). Ниже представлены некоторые варианты для перебора элементов:
Стоит помнить, что если в ходе работы итератора HashMap был изменен (без использования собственным методов итератора), то результат перебора элементов будет непредсказуемым.
Итоги
— Добавление элемента выполняется за время O(1), потому как новые элементы вставляются в начало цепочки;
— Операции получения и удаления элемента могут выполняться за время O(1), если хэш-функция равномерно распределяет элементы и отсутствуют коллизии. Среднее же время работы будет Θ(1 + α), где α — коэффициент загрузки. В самом худшем случае, время выполнения может составить Θ(n) (все элементы в одной цепочке);
— Ключи и значения могут быть любых типов, в том числе и null. Для хранения примитивных типов используются соответствующие классы-оберки;
— Не синхронизирован.
Ссылки
Инструменты для замеров — memory-measurer и Guava (Google Core Libraries).