Как работает linkedhashmap java
Перейти к содержимому

Как работает linkedhashmap java

  • автор:

31.16. Java – Класс LinkedHashMap

Класс LinkedHashMap расширяет HashMap и поддерживает связанный список записей на Map в том порядке, в котором они были вставлены. Это позволяет итерации ввода-вывода по Map. То есть при итерировании LinkedHashMap элементы будут возвращены в том порядке, в котором они были вставлены.

Вы также можете создать LinkedHashMap, который возвращает свои элементы в том порядке, в котором они были в последний раз.

Конструкторы

Ниже приведен список конструкторов, поддерживаемых классом LinkedHashMap.

Конструктор и описание
1 LinkedHashMap( )
Этот конструктор создает стандартную ссылку LinkedHashMap.
2 LinkedHashMap(Map m)
Этот конструктор инициализирует LinkedHashMap с элементами из данного класса Map m.
3 LinkedHashMap(int capacity)
Этот конструктор инициализирует LinkedHashMap с заданной емкостью.
4 LinkedHashMap(int capacity, float fillRatio)
Этот конструктор инициализирует как емкость, так и коэффициент заполнения. Значение емкости и коэффициент заполнения такие же, как для HashMap.
5 LinkedHashMap(int capacity, float fillRatio, boolean Order)
Этот конструктор позволяет указать, будут ли элементы храниться в связанном списке по порядку вставки или по порядку последнего доступа. Если Order = true, используется порядок доступа. Если Order = false, используется порядок вставки.

Методы

Помимо методов, унаследованных от его родительских классов, LinkedHashMap определяет следующие методы:

Методы и описание
1 void clear()
Удаляет все отображения из этого Map.
2 boolean containsKey(Object key)
Возвращает true, если этот Map отображает один и более ключей в указанное значение.
3 Object get(Object key)
Возвращает значение, на которое эта карта отображает указанный ключ.
4 protected boolean removeEldestEntry(Map.Entry eldest)
Возвращает true, если эта карта должна удалить свою старшую запись.

Пример

Следующая программа демонстрирует работу нескольких методов, поддерживаемых коллекцией LinkedHashMap в Java:

import java.util.*; public class LinkedHashMapDemo < public static void main(String args[]) < // Создаём хэш-карту LinkedHashMap lhm = new LinkedHashMap(); // Помещаем элементы в карту lhm.put("Зарина", new Double(3434.34)); lhm.put("Марк", new Double(123.22)); lhm.put("Андрей", new Double(1378.00)); lhm.put("Денис", new Double(99.22)); lhm.put("Михаил", new Double(-19.08)); // Получаем вид элементов Set set = lhm.entrySet(); // Получаем итератор Iterator i = set.iterator(); // Отображаем элементы while(i.hasNext()) < Map.Entry me = (Map.Entry)i.next(); System.out.print(me.getKey() + ": "); System.out.println(me.getValue()); >System.out.println(); // Вносим 1000 на счёт Зарины double balance = ((Double)lhm.get("Зарина")).doubleValue(); lhm.put("Зарина", new Double(balance + 1000)); System.out.println("Новый баланс Зарины: " + lhm.get("Зарина")); > > 

Получим следующий результат:

Зарина: 3434.34 Марк: 123.22 Андрей: 1378.0 Денис: 99.22 Михаил: -19.08 Новый баланс Зарины: 4434.34 

Оглавление

  • 1. Java – Самоучитель для начинающих
  • 2. Java – Обзор языка
  • 3. Java – Установка и настройка
  • 4. Java – Синтаксис
  • 5. Java – Классы и объекты
  • 6. Java – Конструкторы
  • 7. Java – Типы данных и литералы
  • 8. Java – Типы переменных
  • 9. Java – Модификаторы
  • 10. Java – Операторы
  • 11. Java – Циклы и операторы цикла
  • 11.1. Java – Цикл while
  • 11.2. Java – Цикл for
  • 11.3. Java – Улучшенный цикл for
  • 11.4. Java – Цикл do..while
  • 11.5. Java – Оператор break
  • 11.6. Java – Оператор continue
  • 12. Java – Операторы принятия решений
  • 12.1. Java – Оператор if
  • 12.2. Java – Оператор if..else
  • 12.3. Java – Вложенный оператор if
  • 12.4. Java – Оператор switch..case
  • 12.5. Java – Условный оператор (? 🙂
  • 13. Java – Числа
  • 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
  • 13.2. Java – Метод compareTo()
  • 13.3. Java – Метод equals()
  • 13.4. Java – Метод valueOf()
  • 13.5. Java – Метод toString()
  • 13.6. Java – Метод parseInt()
  • 13.7. Java – Метод Math.abs()
  • 13.8. Java – Метод Math.ceil()
  • 13.9. Java – Метод Math.floor()
  • 13.10. Java – Метод Math.rint()
  • 13.11. Java – Метод Math.round()
  • 13.12. Java – Метод Math.min()
  • 13.13. Java – Метод Math.max()
  • 13.14. Java – Метод Math.exp()
  • 13.15. Java – Метод Math.log()
  • 13.16. Java – Метод Math.pow()
  • 13.17. Java – Метод Math.sqrt()
  • 13.18. Java – Метод Math.sin()
  • 13.19. Java – Метод Math.cos()
  • 13.20. Java – Метод Math.tan()
  • 13.21. Java – Метод Math.asin()
  • 13.22. Java – Метод Math.acos()
  • 13.23. Java – Метод Math.atan()
  • 13.24. Java – Метод Math.atan2()
  • 13.25. Java – Метод Math.toDegrees()
  • 13.26. Java – Метод Math.toRadians()
  • 13.27. Java – Метод Math.random()
  • 14. Java – Символы
  • 14.1. Java – Метод Character.isLetter()
  • 14.2. Java – Метод Character.isDigit()
  • 14.3. Java – Метод Character.isWhitespace()
  • 14.4. Java – Метод Character.isUpperCase()
  • 14.5. Java – Метод Character.isLowerCase()
  • 14.6. Java – Метод Character.toUpperCase()
  • 14.7. Java – Метод Character.toLowerCase()
  • 14.8. Java – Метод Character.toString()
  • 15. Java – Строки
  • 15.1. Java – Метод charAt()
  • 15.2. Java – Метод compareTo()
  • 15.3. Java – Метод compareToIgnoreCase()
  • 15.4. Java – Метод concat()
  • 15.5. Java – Метод contentEquals()
  • 15.6. Java – Метод copyValueOf()
  • 15.7. Java – Метод endsWith()
  • 15.8. Java – Метод equals()
  • 15.9. Java – Метод equalsIgnoreCase()
  • 15.10. Java – Метод getBytes()
  • 15.11. Java – Метод getChars()
  • 15.12. Java – Метод hashCode()
  • 15.13. Java – Метод indexOf()
  • 15.14. Java – Метод intern()
  • 15.15. Java – Метод lastIndexOf()
  • 15.16. Java – Метод length()
  • 15.17. Java – Метод matches()
  • 15.18. Java – Метод regionMatches()
  • 15.19. Java – Метод replace()
  • 15.20. Java – Метод replaceAll()
  • 15.21. Java – Метод replaceFirst()
  • 15.22. Java – Метод split()
  • 15.23. Java – Метод startsWith()
  • 15.24. Java – Метод subSequence()
  • 15.25. Java – Метод substring()
  • 15.26. Java – Метод toCharArray()
  • 15.27. Java – Метод toLowerCase()
  • 15.28. Java – Метод toString()
  • 15.29. Java – Метод toUpperCase()
  • 15.30. Java – Метод trim()
  • 15.31. Java – Метод valueOf()
  • 15.32. Java – Классы StringBuilder и StringBuffer
  • 15.32.1. Java – Метод append()
  • 15.32.2. Java – Метод reverse()
  • 15.32.3. Java – Метод delete()
  • 15.32.4. Java – Метод insert()
  • 15.32.5. Java – Метод replace()
  • 16. Java – Массивы
  • 17. Java – Дата и время
  • 18. Java – Регулярные выражения
  • 19. Java – Методы
  • 20. Java – Потоки ввода/вывода, файлы и каталоги
  • 20.1. Java – Класс ByteArrayInputStream
  • 20.2. Java – Класс DataInputStream
  • 20.3. Java – Класс ByteArrayOutputStream
  • 20.4. Java – Класс DataOutputStream
  • 20.5. Java – Класс File
  • 20.6. Java – Класс FileReader
  • 20.7. Java – Класс FileWriter
  • 21. Java – Исключения
  • 21.1. Java – Встроенные исключения
  • 22. Java – Вложенные и внутренние классы
  • 23. Java – Наследование
  • 24. Java – Переопределение
  • 25. Java – Полиморфизм
  • 26. Java – Абстракция
  • 27. Java – Инкапсуляция
  • 28. Java – Интерфейсы
  • 29. Java – Пакеты
  • 30. Java – Структуры данных
  • 30.1. Java – Интерфейс Enumeration
  • 30.2. Java – Класс BitSet
  • 30.3. Java – Класс Vector
  • 30.4. Java – Класс Stack
  • 30.5. Java – Класс Dictionary
  • 30.6. Java – Класс Hashtable
  • 30.7. Java – Класс Properties
  • 31. Java – Коллекции
  • 31.1. Java – Интерфейс Collection
  • 31.2. Java – Интерфейс List
  • 31.3. Java – Интерфейс Set
  • 31.4. Java – Интерфейс SortedSet
  • 31.5. Java – Интерфейс Map
  • 31.6. Java – Интерфейс Map.Entry
  • 31.7. Java – Интерфейс SortedMap
  • 31.8. Java – Класс LinkedList
  • 31.9. Java – Класс ArrayList
  • 31.10. Java – Класс HashSet
  • 31.11. Java – Класс LinkedHashSet
  • 31.12. Java – Класс TreeSet
  • 31.13. Java – Класс HashMap
  • 31.14. Java – Класс TreeMap
  • 31.15. Java – Класс WeakHashMap
  • 31.16. Java – Класс LinkedHashMap
  • 31.17. Java – Класс IdentityHashMap
  • 31.18. Java – Алгоритмы Collection
  • 31.19. Java – Iterator и ListIterator
  • 31.20. Java – Comparator
  • 32. Java – Дженерики
  • 33. Java – Сериализация
  • 34. Java – Сеть
  • 34.1. Java – Обработка URL
  • 35. Java – Отправка Email
  • 36. Java – Многопоточность
  • 36.1. Java – Синхронизация потоков
  • 36.2. Java – Межпоточная связь
  • 36.3. Java – Взаимная блокировка потоков
  • 36.4. Java – Управление потоками
  • 37. Java – Основы работы с апплетами
  • 38. Java – Javadoc

Разница между HashMap, TreeMap и LinkedHashMap в Java

В этом посте будет обсуждаться основное различие между HashMap , TreeMap а также LinkedHashMap классы на Java.

Мы знаем, что Map — это объект, представляющий сопоставление уникальных ключей со значениями. Java предлагает несколько полезных реализаций java.util.Map интерфейс, например HashMap , TreeMap а также LinkedHashMap , которые более-менее похожи по функционалу. В этом посте представлен обзор некоторых основных различий между этими реализациями.

1. Детали реализации

The HashMap а также LinkedHashMap классы реализуют Map интерфейс, тогда как TreeMap реализует Map , NavigableMap , а также SortedMap интерфейс. А HashMap реализован в виде хеш-таблицы, TreeMap реализован как красно-черное дерево, и LinkedHashMap реализован как двусвязный список сегментов в Java.

2. Порядок итерации отображений

Мы знаем, что содержимое карты можно рассматривать как набор ключей, набор значений или набор сопоставлений ключ-значение. Самое главное отличие между HashMap , TreeMap а также LinkedHashMap class лежит в порядке, в котором их итераторы возвращают содержимое карты.

  1. HashMap не дает никаких гарантий относительно порядка итерации карты. Кроме того, добавление и удаление любого элемента может изменить его порядок итерации.
  2. TreeMap , с другой стороны, повторяется в соответствии с естественным порядком его ключей или в соответствии с Компаратором, указанным во время создания карты.
  3. LinkedHashMap поддерживает двусвязный список во всех своих записях. Этот связанный список определяет порядок итерации, то есть порядок, в котором ключи были вставлены в карту.

Вот простая программа на Java, иллюстрирующая порядок итерации HashMap , TreeMap а также LinkedHashMap .

import java . util . HashMap ;
import java . util . LinkedHashMap ;
import java . util . Map ;
import java . util . TreeMap ;
class Main
public static void main ( String [ ] args )
Map < String , String >hm = new LinkedHashMap <> ( ) ;
hm . put ( «USA» , «Washington» ) ;
hm . put ( «United Kingdom» , «London» ) ;
hm . put ( «India» , «New Delhi» ) ;
System . out . println ( «LinkedHashMap : » + hm ) ;
hm = new TreeMap <> ( hm ) ;
System . out . println ( «TreeMap : » + hm ) ;
hm = new HashMap <> ( hm ) ;
System . out . println ( «HashMap : » + hm ) ;

3. Производительность

Предполагая, что хеш-функция правильно распределяет элементы по сегментам, HashMap а также LinkedHashMap предложения O(1) время выполнения основных операций, таких как получение, установка, containsKey, удаление и т. д., с другой стороны, TreeMap гарантии O(log(n)) затраты времени на эти операции.

Обратите внимание, что из-за дополнительных расходов на поддержку двусвязного списка LinkedHashMap производительность немного ниже, чем у HashMap . Итак, если производительность является проблемой, HashMap является предпочтительным.

Теперь переходя к космической сложности, HashMap требует меньше памяти, чем TreeMap а также LinkedHashMap поскольку он использует хеш-таблицу для хранения сопоставлений. LinkedHashMap имеет дополнительные накладные расходы на двусвязный список, и TreeMap реализовано в виде красно-черного дерева, которое занимает больше памяти.

4. Нулевые значения/ключи

HashMap а также LinkedHashMap допускает нулевые значения и нулевой ключ, тогда как TreeMap разрешает только нулевые значения (не нулевые ключи), если используется естественный порядок ключей. Он поддерживает нулевые ключи только в том случае, если его компаратор поддерживает сравнение нулевых ключей.

Какую реализацию использовать?

Использовать HashMap когда производительность критична, а порядок ключей не имеет значения.
Использовать TreeMap когда ключи необходимо упорядочить, используя их естественный порядок или с помощью компаратора.
Использовать LinkedHashMap если порядок вставки ключей должен быть сохранен.

Это все о различиях между HashMap, TreeMap и LinkedHashMap в Java.

Оценить этот пост

Средний рейтинг 4.73 /5. Подсчет голосов: 41

Голосов пока нет! Будьте первым, кто оценит этот пост.

Сожалеем, что этот пост не оказался для вас полезным!

Расскажите, как мы можем улучшить этот пост?

LinkedHashMap

LinkedHashMap — отображение с запоминанием порядка, в котором добавлялись элементы, разрешает перебор в порядке вставки.

Общий ознакомительный пример.

 LinkedHashMap linkedHashMap = new LinkedHashMap<>(); linkedHashMap.put("one", 1); linkedHashMap.put("two", 2); linkedHashMap.put("three", 3); linkedHashMap.put("four", 4); linkedHashMap.put("five", 5); Set set = linkedHashMap.entrySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()) < Map.Entry item = (Map.Entry) iterator.next(); System.out.println("Key = " + item.getKey() + " Value bg-light"> I/System.out: Key = one Value = 1 I/System.out: Key = two Value = 2 I/System.out: Key = three Value = 3 I/System.out: Key = four Value = 4 I/System.out: Key = five Value = 5 

Использование класса LinkedHashMap

Предположим, что вы пишете Java-приложение, использующее словарь слов, например, при подсчете частоты имеющихся в тексте слов. В самом начале программы производится вставка слов в хэш-таблицу. Затем, при обнаружении каждого слова, приложение находит слово в таблице и увеличивает его частоту на единицу.

Вот код, использующий этот подход:

import javax.net.ssl.*;
import javax.net.*;
import java.io.*;
import java.net.*;

public class EchoServer private static final int PORT_NUM = 6789 ;

public static void main ( String args []) ServerSocketFactory serverSocketFactory = SSLServerSocketFactory
.getDefault () ;
ServerSocket serverSocket = null ;
try serverSocket = serverSocketFactory.createServerSocket ( PORT_NUM ) ;
> catch ( IOException ignored ) System.err.println ( "Unable to create server" ) ;
System.exit ( - 1 ) ;
>
while ( true ) Socket socket = null ;
try socket = serverSocket.accept () ;
InputStream is = socket.getInputStream () ;
BufferedReader br = new BufferedReader ( new InputStreamReader (
is, "US-ASCII" )) ;
OutputStream os = socket.getOutputStream () ;
Writer writer = new OutputStreamWriter ( os, "US-ASCII" ) ;
PrintWriter out = new PrintWriter ( writer, true ) ;
String line = null ;
while (( line = br.readLine ()) != null ) out.println ( line ) ;
>
> catch ( IOException exception ) exception.printStackTrace () ;
> finally if ( socket != null ) try socket.close () ;
> catch ( IOException ignored ) >
>
>
>
>
>

После выполнения этой программы вы получите следующий результат:

computer 1 able 1 baker 2

То есть, "computer" использовался один раз, а "baker" два.

Эти результаты верны, но существует потенциальная проблема: слова отображаются не в том порядке, в котором первоначально были вставлены в хэш-таблицу. Эта проблема связана с внутренней работой хэш-таблиц. Сортировка в такой таблице случайна.

Сортировка хэш-таблицы

Вы можете не беспокоиться о смешанной сортировке, поскольку выполнение главной функции хэш-таблицы не зависит от порядка пар ключ/значение. Но если для вас это важно, существует ли решение? Одним из ответов на этот вопрос является использование LinkedHashMap вместо HashMap. Вы можете сделать это, поменяв одну строку в приведенной выше программе, а именно строку, в которой создается объект HashMap в начале определения класса MapDemo1. Другими словами, закомментируйте строку:

static Map map = new HashMap () ;

Затем раскомментируйте строку:

static Map map = new LinkedHashMap () ;

LinkedHashMap аналогичен HashMap, за исключением того, что он налагает структуру связного списка на верхнюю часть хэш-таблицы. Этот список хранит порядок вставки элементов таблицы. Затем он используется для итерации по таблице.

После изменения одной строки в MapDemo1, результат работы программы будет следующим:

able 1 baker 2 computer 1

Элементы сейчас отображаются в алфавитном порядке, поскольку именно в этом порядке они были вставлены в хэш-таблицу. LinkedHashMap не сортирует свои элементы. Он просто сохраняет порядок их вставки.

Копирование таблицы

Рассмотрим еще один пример. Предположим, что вы пишите метод, в котором надо скопировать таблицу и в дальнейшем работать с этой копией. В этой ситуации может быть важным сохранить порядок элементов в копии таблицы. Результаты ваших операций с таблицей предсказуемы. Вот программа, демонстрирующая эту идею:

public class MapDemo2

// скопировать таблицу
static Map copyMap ( Map map ) return new HashMap ( map ) ;
//return new LinkedHashMap(map);
>

public static void main ( String args [])

// создать TreeMap и
// добавить несколько пар ключ/значение

Map map_tree = new TreeMap () ;
map_tree.put ( "able" , "value1" ) ;
map_tree.put ( "baker" , "value2" ) ;
map_tree.put ( "computer" , "value3" ) ;

Map map_copy = copyMap ( map_tree ) ;

// отобразить содержимое таблицы

Iterator iter = map_copy.keySet () .iterator () ;
while ( iter.hasNext ()) System.out.println ( iter.next ()) ;
>
>
>

Этот пример опять использует словарь. В этой программе слова словаря добавляются в TreeMap - класс, гарантирующий, что его элементы будут отсортированы в порядке возрастания ключа.

Предположим, что вы хотите скопировать TreeMap, и сохранить порядок сортировки. Но вы не нуждаетесь в полной структуре TreeMap, реализованной в J2SE(tm) v 1.4 с использованием "красно-черных деревьев". (Если вы не знакомы с красно-черными деревьями, обратитесь к книге "Введение в алгоритмы" Cormen, Leiserson и Rivest.) Как сделать такую копию?

Первый подход в MapDemo2 использует HashMap, то есть:

static Map copyMap ( Map map ) <
return new HashMap ( map ) ;
> Вот результат:

computer able baker

Проблема здесь аналогична продемонстрированной ранее - хэш-таблица хранит свои элементы в произвольном порядке. Элементы в TreeMap отсортированы, но после копирования их в HashMap порядок нарушается.

Если программу MapDemo2 изменить на использование LinkedHashMap, например:

static Map copyMap ( Map map ) <
return new LinkedHashMap ( map ) ;
>

то результат будет следующим:

able baker computer

В хэш-таблице все равно нарушен порядок элементов, но у нас имеется также связный список, хранящий порядок вставки элементов. Этот список используется для итерации по элементам.

Сохранение порядка доступа к элементам

Существует еще один способ использования LinkedHashMap. Если вы создадите таблицу с помощью значения "true", переданного в качестве третьего аргумента в конструктор, например:

Map map = new LinkedHashMap ( 16 , 0.75f , true ) ;

то будет сохраняться не порядок вставки, а порядок доступа к элементам. Каждый вызов get или put представляет собой доступ к элементу. Порядок итерации - от самого старого к самому новому. Рассмотрим пример:

public class MapDemo3 public static void main ( String args [])

// создать map и
// добавить несколько пар ключ/значение

Map map = new LinkedHashMap ( 16 , 0.75f , true ) ;
map.put ( "able" , "value1" ) ;
map.put ( "baker" , "value2" ) ;
map.put ( "computer" , "value3" ) ;

// отобразить содержимое таблицы

Iterator iter1 = map.keySet () .iterator () ;
while ( iter1.hasNext ()) System.out.println ( iter1.next ()) ;
>

// использовать элементы таблицы

map.get ( "baker" ) ;
map.get ( "able" ) ;
map.get ( "computer" ) ;

// опять отобразить содержимое таблицы

System.out.println () ;
Iterator iter2 = map.keySet () .iterator () ;
while ( iter2.hasNext ()) System.out.println ( iter2.next ()) ;
>
>
>

После выполнения этой программы вы получите следующий результат:

able baker computer baker able computer

Первая часть результата отображает последовательность вызовов put. Вызов put для "able" старше, чем вызов put для "computer". Затем выполняются вызовы get. Первый вызов get делается для "baker", затем для "able" и "computer".

Извлечение элементов таблицы в порядке доступа к ним очень полезен в некоторых приложениях, например, если вы работаете с кэшем и хотите освободить старые элементы. Если вы поместите элементы кэша в LinkedHashMap, каждое обращение к элементу автоматически будет обновлять порядок. То есть, в любое время вы можете определить, какие элементы являются самыми старыми и при желании удалить их. Такая схема работы часто называется кешем LRU или "least recently used" (кэш с замещением элементов с наиболее давним использованием).

Ссылки

Дополнительная информация о LinkedHashMap находится в описании класса.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *