Набор данных интерфейса Map

Интерфейс Map располагается на вершине иерархии в Java Collection. Он входит в состав JDK начиная с версии 1.2, предоставляя разработчику базовые методы для работы с данными вида «ключ — значение». Функции интерфейса расширяются вместе с развитием технологий Java. Полную англоязычную документацию интерфейса Map можно найти здесь.

Иерархия интерфейса Map представлена на рисунке.

Наиболее часто используемые методы интерфейса Map

МетодОписание
void clear() Очистка хеш-таблицы
boolean containsKey(Object key) Функция проверки присутствия объекта по ключу
boolean containsValue(Object value) Функция проверки присутствия объекта по значению
Set<Map.Entry<K,V>> entrySet() Функция получения объекта в виде коллекции Set
boolean equals(Object object) Функция сравнения с объектом object
Object get(Object key) Функция получения записи по ключу
boolean isEmpty() Функция проверки наличия записей
Set<K> keySet() Функция получения записей в виде коллекции Set
void put(K key, V value) Функция добавления записи
void putAll(Map<? extends K,? extends V> t) Функция добавления записей
void remove(Object key) Метод удаления объекта по ключу key
boolean remove(Object key, Object value) Функция удаления записи по соответствию значений ключа и значения
void replace(K key, V value) Замена значения value для записи с ключом key
boolean replace(K key, V oldValue, V newValue) Замена значения oldValue на newValue для записи с ключом key
int size() Функция определения количества записей в хеш-таблице
Collection<V> values() Получение значений записей в виде коллекции

Описание Hashtable

Класс Hashtable позволяет реализовывать структуру данных типа hash-таблица, содержащую пары вида "ключ - значение". Значение "null" в качестве значения или ключа использовать нельзя. Hashtable является синхронизированной, т.е. почти все методы помечены как synchronized, в связи с чем могут быть проблемы с производительностью.

Экземпляр Hashtable включает два параметра, влияющие на его производительность. Это начальная емкость и коэффициент загрузки. Начальная емкость формируется на этапе создания объекта.

Коэффициент загрузки определяет объем информации, по достижении которого емкость Hashtable автоматически будет увеличена. Обычно, значение коэффициента загрузки равно 0.75. Более высокие значения уменьшают издержки пространства, но увеличивают стоимость времени поиска записи.

Полную документацию по Hashtable можно найти здесь.

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

  • Hashtable()
    Создание хеш-таблицы с емкостью по умолчанию (11 записей) и коэффициент загрузки по умолчанию (0.75).
  • Hashtable(int initialCapacity)
    Создание хеш-таблицы с указанной начальной емкостью и коэффициентом загрузки по умолчанию (0.75).
  • Hashtable(int initialCapacity, float loadFactor)
    Создание хеш-таблицы с указанной начальной емкостью и указанным коэффициентом загрузки.
  • Hashtable(Map<? extends K,? extends V> t)
    Создание хеш-таблицы с указанными параметрами.

Дополнительные методы Hashtable

Hashtable реализует все методы интерфейса Map и включает дополнительно следующие методы :

МетодОписание
Объект clone() Создание копии хеш-таблицы
boolean contains(Object value) Функция проверки присутствия объекта value в хеш-таблице
Enumeration<V> elements() Получение ключей хеш-таблицы в виде объекта Enumeration
Enumeration<K> keys() Функция получения ключей хеш-таблицы в виде объекта Enumeration
void rehash() реорганизация hash ключей и увеличение емкости

В качестве примера рассмотрим задачу организации небольшого телефонного справочника с помощью Hashtable, позволяющего использовать механизм хеш-таблиц для эффективного поиска записей по ключу. С помощью метода put программа добавляет новые записи в хеш-таблицу. Извлечение записей выполняется методом get, которому в качестве параметра передается ключ.

Пример телефонного справочника, содержащего имена и телефоны :

Hashtable phoneBook = new Hashtable();

// Добавление записей в справочник

phoneBook.put("Оксана Л.", "(926) 111-222-333");
phoneBook.put("Сергей М.", "(929) 333-222-111");
phoneBook.put("Петр Ж."  , "(915) 333-111-222");
phoneBook.put("Михаил Н.", "(926) 222-333-111");

Для добавления записей используется метод put, которому в качестве параметров передается "ключ" (первый параметр - имя) и "значение" (второй параметр - телефон). Для чтения списка ключей используется метод keys класса Hashtable, который возвращает объект класса Enumeration.

// Список ключей
Enumeration keys = phoneBook.keys();

while (en.hasMoreElements()) {
    String user  = (String) keys.nextElement();
    String value = (String) phoneBook.get(user);
    System.out.println("key (user) = " + user + ", value (phone) = " + value); 
}

Условие завершения цикла - возвращение методом hasMoreElements значения "false". С помощью метода nextElement в цикле извлекаются все значения ключей, а затем методом get получаем соответствующие этим ключам значения.

Набор данных HashMap

Набор данных HashMap является альтернативой Hashtable. Основными отличиями от Hashtable являются то, что HashMap не синхронизирован и позволяет использовать null как в качестве ключа, так и значения.

Также как и Hashtable, коллекция HashMap не является упорядоченной: порядок хранения элементов зависит от хэш-функции. Реализация HashMap обеспечивает постоянно-разовую производительность для основных операций (get и put).

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

Полную документацию по HashMap можно найти здесь.

Конструкторы и описание HashMap

МетодОписание
HashMap() Конструктор с используемыми по умолчанию значениями начальной емкости (16) и коэффициентом загрузки (0.75)
HashMap(int initialCapacity) Конструктор с используемым по умолчанию значением коэффициентом загрузки (0.75) и начальной емкостью initialCapacity
HashMap(int initialCapacity, float loadFactor) Конструктор с используемыми значениями начальной емкости initialCapacity и коэффициентом загрузки loadFactor
HashMap(Map<? extends K,? extends V> m) Конструктор с определением структуры согласно объекту-параметра.

Пример использования методов HashMap.

import java.util.Set;
import java.util.Map;
import java.util.HashMap;

public class TestHashMap
{
    public static void main(String[] a)
    {
        Map<String, String> map = new HashMap<String, String>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");

        System.out.println(map);

        Map<String, String> map2 = new HashMap<String, String>();
        map.put("key4", "value4");
        map.put("key5", "value5");
        map.put("key6", "value6");

        // Добавление набора данных 
        map.putAll(map2);
        // Удаление объекта по ключу 
        map.remove("key5");
        // Размер набора
        System.out.println("Размер набора данных : " + map.size());
        // Поиск по ключу
        String exists = (map.containsKey("key2")) ? "найден" : "не найден";
        System.out.println("Объект с ключом 'key2' " + exists);	
        // Поиск по значению
        exists = (map.containsValue("value2")) ? "найден" : "не найден";
        System.out.println("Объект со значением 'value2' " + exists);
        // Перебор значений
        Set<Map.Entry<String, String>> set = map.entrySet();
        for (Map.Entry<String, String> me : set) {
             System.out.print("ключ : " + me.getKey() + ", значение = " + me.getValue());
        }
        // Очистка объекта
        map.clear();
    }
}

Результат работы программы :

{key3=value3, key2=value2, key1=value1}
Размер набора данных : 5
Объект с ключом 'key2' найден
Объект со значением 'value2' найден
Список записей набора :
  ключ : key4, значение = value4
  ключ : key3, значение = value3
  ключ : key6, значение = value6
  ключ : key2, значение = value2
  ключ : key1, значение = value1

Хэш-таблицы LinkedHashMap

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

Конструкторы и описание LinkedHashMap

МетодОписание
LinkedHashMap() Конструктор с используемыми по умолчанию значениями начальной емкости (16) и коэффициентом загрузки (0.75)
LinkedHashMap(int initialCapacity) Конструктор с используемым по умолчанию значением коэффициентом загрузки (0.75) и начальной емкостью initialCapacity
LinkedHashMap(int initialCapacity, float loadFactor) Конструктор с используемыми значениями начальной емкости initialCapacity и коэффициентом загрузки loadFactor
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) Конструктор с используемыми значениями начальной емкости initialCapacity и коэффициентом загрузки loadFactor. accessOrder - the ordering mode - true for access-order, false for insertion-order
LinkedHashMap(Map<? extends K,? extends V> m) Конструктор с определением структуры согласно объекта-параметра.

Полную документацию по LinkedHashMap можно найти здесь.

Пример использования LinkedHashMap :

import java.util.LinkedHashMap; 
import java.util.Map; 

public class TestLinkedHashMap
{ 
    public static void main(String[] args)
    { 
        // Представление списка товаров набором значений (key, value)
        Map<String, Double> linkedHashMap = new LinkedHashMap<String, Double>(); 
        linkedHashMap.put("Apple", new Double(91.98)); 
        linkedHashMap.put("Sony" , new Double(16.76)); 
        linkedHashMap.put("Dell" , new Double(30.47)); 
        linkedHashMap.put("HP"   , new Double(33.91)); 
        linkedHashMap.put("IBM"  , new Double(181.71)); 

        // Отображение в консоле содержания объекта map linkedHashMap
        System.out.println("Содержимое : " + linkedHashMap); 

        // Представление записей набора в цикле
        System.out.println("Значения записей : "); 
        for (String key : linkedHashMap.keySet()) { 
            System.out.println(key + ":\t" + linkedHashMap.get(key)); 
        } 
        // Получение значения цены IBM по ключу
        System.out.println("Значение цены IBM : " + linkedHashMap.get("IBM")); 
        // Размер linkedHashMap 
        System.out .println("Размер linkedHashMap : " + linkedHashMap.size()); 
        // Проверка наличия записей
        System.out.println("Является ли linkedHashMap пустым ? : " + 
		                    linkedHashMap.isEmpty()); 
        // Проверка наличия записей по ключу и значению
        System.out.println("linkedHashMap содержит запись Sony о ключу ? : " + 
		                    linkedHashMap.containsKey("Sony")); 
        System.out.println("LinkedHashMap содержит запись со значением 666.0? : " + 
		                    linkedHashMap.containsValue(999.0)); 
        // Удаление записи Dell
        System.out.println(linkedHashMap.remove("Dell")); 
        // Очистка набора данных
        linkedHashMap.clear(); 
    } 
}

Результат работы программы :


Содержимое : {Apple=91.98, Sony=16.76, Dell=30.47, HP=33.91, IBM=181.71}
Значения записей : 
Apple:	91.98
Sony:	16.76
Dell:	30.47
HP:	33.91
IBM:	181.71
Значение цены IBM : 181.71
Размер linkedHashMap : 5
Является ли linkedHashMap пустым ? : false
linkedHashMap содержит запись Sony о ключу ? : true
LinkedHashMap содержит запись со значением 666.0? : false
30.47
 

Набор данных TreeMap

TreeMap, как и LinkedHashMap, является упорядоченным набором данных. По-умолчанию, TreeMap сортируется по ключам с использованием принципа "natural ordering". Но это поведение может быть настроено под конкретную задачу при помощи объекта Comparator, который указывается в качестве параметра при создании объекта TreeMap.

Конструкторы и описание TreeMap

МетодОписание
TreeMap() Пустой конструктор создания объекта без упорядочивания данных (using the natural ordering of its keys)
TreeMap(Comparator<? super K> comparator) Конструктор создания объекта с упорядочиванием значений согласно comparator
TreeMap(Map<? extends K,? extends V> m) Конструктор с определением структуры согласно объекту-параметра
TreeMap(SortedMap<K,? extends V> m) Конструктор с определением структуры и сортировки согласно объекту-параметра.

Полную документацию по TreeMap можно найти здесь.

import jаvа.util.*;
 
public class TestTreeMap
{
    public static void main(String[] args)
    {
        System.out.println("Пример использования TreeMap :");
        TreeMap <Integer, String> map = new TreeMap<Integer, String>();
        // Добавляем данные
        map.put(1, "Понедельник");
        map.put(2, "Вторник"    );
        map.put(3, "Среда"      );
        map.put(4, "Четверг"    );
        map.put(5, "Пятница"    );
        map.put(6, "Суббота"    );
        map.put(7, "Воскресенье");
        // Получаем все ключи
        System.out.println("Ключи : " + map.keySet());
        // Получаем все значения
        System.out.println("Значения : " + map.values());
        // Получаем пятое значение
        System.out.println("Ключ = 3, значение = " + map.get(3));
        // Получаем первый ключ и его значение
        System.out.println("Первый ключ : " + map.firstKey() + ", значение : " + map.get(map.firstKey()));
        // Получаем последний ключ и значение
        System.out.println("Последний ключ : " + map.lastKey() + ", значение : " + map.get(map.lastKey()));
        // Удаляем первый ключ и значение
        System.out.println("Удаляем первую запись : " + map.remove(map.firstKey()));
        System.out.println("Ключи : " + map.keySet());
        System.out.println("Значения : " + map.values());
        // Удаляем последний ключ и значение
        System.out.println("Удаляем последнее значение : " + map.remove(map.lastKey()));
        System.out.println("Ключи : " + map.keySet());
        System.out.println("Значения : " + map.values());
    }
}

Результат работы программы :

Пример использования TreeMap :
Ключи : [1, 2, 3, 4, 5, 6, 7]
Значения : [Понедельник, Вторник, Среда, Четверг, Пятница, Суббота, Воскресенье]
Ключ = 3, значение = Среда
Первый ключ : 1, значение : Понедельник
Последний ключ : 7, значение : Воскресенье
Удаляем первую запись : Понедельник
Ключи : [2, 3, 4, 5, 6, 7]
Значения : [Вторник, Среда, Четверг, Пятница, Суббота, Воскресенье]
Удаляем последнее значение : Воскресенье
Ключи : [2, 3, 4, 5, 6]
Значения : [Вторник, Среда, Четверг, Пятница, Суббота]

Пример программы использования TreeMap с Comparator'ом

import java.util.Map.Entry;
import java.util.*;

public class SortedTreeMap implements Comparator<Object>
{
    private TreeMap<String, String> tm = new TreeMap<String, String>();

    public SortedTreeMap()
    {
        tm.put("33", "book" );
        tm.put("11", "art"  );
        tm.put("22", "cook" );
        tm.put("24", "dog"  );
        tm.put("31", "cool" );
        tm.put("14", "rest" );
        tm.put("12", "lost" );
        tm.put("11", "value");

        TreeMap<String, String> tm1 = new TreeMap<String, String>();
        tm1.putAll (tm);
        Iterator<Entry<String, String>> it = tm1.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String, String> me = (Map.Entry<String, String>)it.next();
            System.out.println(me.getKey() + "  " + (String)me.getValue());
        }
    }
    public int compare( Object o1, Object o2 )
    {
        return ((String)tm.get( o1 )).compareTo( (String)tm.get( o2 )) ;
    }
    public static void main( String[] args )
    {
        new SortedTreeMap();
    }
}

Результат работы программы :


11  value
12  lost
14  rest
22  cook
24  dog
31  cool
33  book
 
Наверх
  Рейтинг@Mail.ru