Страницы

Поиск по вопросам

Показаны сообщения с ярлыком java-hashmap. Показать все сообщения
Показаны сообщения с ярлыком java-hashmap. Показать все сообщения

пятница, 14 февраля 2020 г.

Java: Запись массива в HashMap

#java #массивы #java_hashmap


Есть HashMap map при простой записи 

map.put("v",{true, false, true, true}); 


IDE выдает ошибку, что нельзя делать так 
Но, если же я до этого создам отдельный массив 

boolean[] bool = {true, false, true, true}


И потом заброшу bool то все работает 
Однако, таких последовательностей многовато, и не совсем удобно (даже для памяти)
создавать каждый раз новую переменную массив 
Каким образом можно сделать это попроще?
    


Ответы

Ответ 1



map.put("v", new boolean[] {true, false, true});

четверг, 13 февраля 2020 г.

Инициализация интерфейса Map

#java #коллекции #java_hashmap


Что происходит в данной записи ?

Map m =  new HashMap();


Интерфейс Map  через полиморфизм инициализируется  классом потомком   "HashMap" ? 
Для чего это делается ?

Map m; 
for (int i = 0; i < aProduct.length; i++) {

    m = new HashMap(); 

    m.put(ATTRIBUTE_NAME_TEXT, aProduct[i]);
    m.put(ATTRIBUTE_NAME_PR, aPrice[i]);
    m.put(ATTRIBUTE_NAME_QT, aQuantity[i]);
    data.add(m);
}

    


Ответы

Ответ 1



Смысл есть. А если в будущем вы захотите использовать не HashMap, а другую реализацию Map? Конечно, можно делать как вам вздумается. А сделано для того, чтобы можно было на лету менять конечную реализацию (к примеру, вместо HashMap использовать LinkedHashMap). Поэтому и принято оперировать интерфейсами. Чтобы не связывать свой код жестко конкретными реализациями.

пятница, 31 января 2020 г.

Найти хэш-таблицу в HashMap

#java #коллекции #java_hashmap


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

Когда я залез в исходники HashMap, то увидел следующее:

transient Node[] table;


Если я все правильно понял, и это и есть хеш-таблица, то почему тогда это одномерный
массив? Или я что-то не то нашел, и это не она?
    


Ответы

Ответ 1



Представленный Вами массив является основой для хранения хэш-таблицы. Но кроме этого, каждый элемент такого массива (bucket) содержит ссылку на первый элемент linked list (JDK 7 и ранее), либо ссылку на первый элемент linked list/ссылку на корневой узел balanced tree (JDK 8). В linked list, либо в balanced tree находятся пары, которые попали в одну и ту же корзину. Пример для связного списка: Таким образом и хранится эта хэш-таблица.

Ответ 2



Если бы вы посмотрели, что это за класс, то увидели бы, что это он реализует помимо всего прочего еще и односвязный список static class Node implements Map.Entry { final int hash; final K key; V value; Node next; // simple, isn't it? Также есть TreeNode, который является наследником Node, чтобы в сложных случаях можно было реализовать хранение одной корзины не списком, а деревом.

Ответ 3



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

среда, 1 января 2020 г.

Разве Hashmap сортируется автоматичски?

#java #java_hashmap


Написал тестовый код, чтоб объяснить проблему. 

mport java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        HashMap map = new HashMap<>();
        map.put(6,"A");
        map.put(3,"B");
        map.put(2,"C");
        map.put(7,"D");
        map.put(1,"E");

        for (Object obj :
                map.entrySet()) {
            Map.Entry  pair = (Map.Entry ) obj;
            System.out.println(pair.getKey()+" "+pair.getValue());
        }
    }
}

Консоль: 
1 E
2 C
3 B
6 A
7 D


Почему HashMap автоматически сортирует карты по ключу? Ведь насколько я знаю, он
не должен этого делать.....
    


Ответы

Ответ 1



Хэш целого числа - это само значения этого числа, поэтому по бакетам числа распределятся последовательно и, соответственно, выведены тоже будут последовательно.

пятница, 13 декабря 2019 г.

Сигнатуры методов HashMap

#java #generics #java_hashmap #hashmap


Почему метод put принимает на вход key параметр типа K:

public V put(K key, V value)


а метод get принимает на вход key параметр типа Object?

public V get(Object key)


Я пробовала в своей упрощённой реализации HashMap использовать методы

public V get(K key) 
public V put(K key, V value) 


и это работает, точно так же, как работает и 

public V get(Object  key) 
public V put(Object  key, Object value) 


Насколько я понимаю, метод put должен принимать именно K key и V value, потому что
в теле этого метода вызывается метод

void addEntry(int hash, K key, V value, int bucketIndex) 


и без явного приведения типов (addEntry(hash, (K) key, (V) value, i);) вызов этого
метода вызвал бы ошибку компиляции, если бы key и value были бы типа Object. Но почему
метод  get принимает на вход key параметр типа Object, а не K? Ведь это же как-то некрасиво,
что ли (разный стиль)... и в этом должен быть, наверное, какой-то особый смысл.
    


Ответы

Ответ 1



Оргиниал ответа Всё дело в том, что спецификация Map не требует того, чтобы все ключи имели одинаковый тип. Она лишь требует корректного поведения метода equals (и hashCode для HashMap) для объектов, которые используются в качестве ключей. Конечно реализация метода equals обычно требует, чтобы совпадали, в том числе, классы сравниваемых объектов. Но есть случаи, где имеется другое поведение. К примеру при сравнении реализаций java.util.List (ArrayList, LinkedList и т.д.) требуется лишь, чтобы было эквивалентно именно содержимое этих списков. По указанной причине вы можете объявить переменную с типом Map при этом в метод get передавать переменную типа LinkedList и это будет вполне рабочий вариант. Если же задаваться вопросом зачем объявлять Map вместо Map, то я могу привести, хоть и узконаправленный, но всё же пример. Представьте, что ваша переменная с типом Map периодически сериализуется, и вам очень важно быстродействие указанной сериализации. Поэтому вы требуете явно, чтобы записываемые ключи был именно указанного типа (я сейчас не буду говорить о реальной скорости сериализации ArrayList). А при поиске объекта-значения в метод get вы можете передавать аргумент любого типа, к примеру тот же LinkedList, что немного упростит вам жизнь. P.S. На эту тему можно конечно подискутировать, но таковы реалии Java. Вполне возможно, что это недостаток проектирования. И ссылаясь на этот ответ могу сказать, что пытались сделать нечто подобное, но возникли некоторые трудности, и от этой идеи отказались.

вторник, 2 апреля 2019 г.

Найти хэш-таблицу в HashMap

Начав исследовать такое явление как hash-таблица, я понял, что это некий массив, каждая ячейка которого хранит список, который параметризован двумя типами: ключ и значение.
Когда я залез в исходники HashMap, то увидел следующее:
transient Node[] table;
Если я все правильно понял, и это и есть хеш-таблица, то почему тогда это одномерный массив? Или я что-то не то нашел, и это не она?


Ответ

Представленный Вами массив является основой для хранения хэш-таблицы.
Но кроме этого, каждый элемент такого массива (bucket) содержит ссылку на первый элемент linked list (JDK 7 и ранее), либо ссылку на первый элемент linked list/ссылку на корневой узел balanced tree (JDK 8).
В linked list, либо в balanced tree находятся пары, которые попали в одну и ту же корзину.
Пример для связного списка:

Таким образом и хранится эта хэш-таблица.

пятница, 2 ноября 2018 г.

Сигнатуры методов HashMap

Почему метод put принимает на вход key параметр типа K
public V put(K key, V value)
а метод get принимает на вход key параметр типа Object?
public V get(Object key)
Я пробовала в своей упрощённой реализации HashMap использовать методы
public V get(K key) public V put(K key, V value)
и это работает, точно так же, как работает и
public V get(Object key) public V put(Object key, Object value)
Насколько я понимаю, метод put должен принимать именно K key и V value, потому что в теле этого метода вызывается метод
void addEntry(int hash, K key, V value, int bucketIndex)
и без явного приведения типов (addEntry(hash, (K) key, (V) value, i);) вызов этого метода вызвал бы ошибку компиляции, если бы key и value были бы типа Object. Но почему метод get принимает на вход key параметр типа Object, а не K? Ведь это же как-то некрасиво, что ли (разный стиль)... и в этом должен быть, наверное, какой-то особый смысл.


Ответ

Оргиниал ответа
Всё дело в том, что спецификация Map не требует того, чтобы все ключи имели одинаковый тип. Она лишь требует корректного поведения метода equals (и hashCode для HashMap) для объектов, которые используются в качестве ключей.
Конечно реализация метода equals обычно требует, чтобы совпадали, в том числе, классы сравниваемых объектов. Но есть случаи, где имеется другое поведение. К примеру при сравнении реализаций java.util.List (ArrayList, LinkedList и т.д.) требуется лишь, чтобы было эквивалентно именно содержимое этих списков. По указанной причине вы можете объявить переменную с типом Map при этом в метод get передавать переменную типа LinkedList и это будет вполне рабочий вариант.
Если же задаваться вопросом зачем объявлять Map вместо Map, то я могу привести, хоть и узконаправленный, но всё же пример. Представьте, что ваша переменная с типом Map периодически сериализуется, и вам очень важно быстродействие указанной сериализации. Поэтому вы требуете явно, чтобы записываемые ключи был именно указанного типа (я сейчас не буду говорить о реальной скорости сериализации ArrayList). А при поиске объекта-значения в метод get вы можете передавать аргумент любого типа, к примеру тот же LinkedList, что немного упростит вам жизнь.
P.S. На эту тему можно конечно подискутировать, но таковы реалии Java. Вполне возможно, что это недостаток проектирования. И ссылаясь на этот ответ могу сказать, что пытались сделать нечто подобное, но возникли некоторые трудности, и от этой идеи отказались.