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

161
23 августа 2018, 05:30

Почему метод 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? Ведь это же как-то некрасиво, что ли (разный стиль)... и в этом должен быть, наверное, какой-то особый смысл.

Answer 1

Оргиниал ответа

Всё дело в том, что спецификация Map не требует того, чтобы все ключи имели одинаковый тип. Она лишь требует корректного поведения метода equalshashCode для HashMap) для объектов, которые используются в качестве ключей.

Конечно реализация метода equals обычно требует, чтобы совпадали, в том числе, классы сравниваемых объектов. Но есть случаи, где имеется другое поведение. К примеру при сравнении реализаций java.util.List (ArrayList, LinkedList и т.д.) требуется лишь, чтобы было эквивалентно именно содержимое этих списков. По указанной причине вы можете объявить переменную с типом Map<ArrayList, String> при этом в метод get передавать переменную типа LinkedList и это будет вполне рабочий вариант.

Если же задаваться вопросом зачем объявлять Map<ArrayList, String> вместо Map<List, String>, то я могу привести, хоть и узконаправленный, но всё же пример. Представьте, что ваша переменная с типом Map<ArrayList, String> периодически сериализуется, и вам очень важно быстродействие указанной сериализации. Поэтому вы требуете явно, чтобы записываемые ключи был именно указанного типа (я сейчас не буду говорить о реальной скорости сериализации ArrayList). А при поиске объекта-значения в метод get вы можете передавать аргумент любого типа, к примеру тот же LinkedList, что немного упростит вам жизнь.

P.S. На эту тему можно конечно подискутировать, но таковы реалии Java. Вполне возможно, что это недостаток проектирования. И ссылаясь на этот ответ могу сказать, что пытались сделать нечто подобное, но возникли некоторые трудности, и от этой идеи отказались.

READ ALSO
Вывод данных в ReclerView Firebase

Вывод данных в ReclerView Firebase

Есть база данных Firebase с такой структурой:

158
Экранирование в POST запросе

Экранирование в POST запросе

У меня есть REST-сервис:

175
Оптимизация кода (алгоритм Крускала)

Оптимизация кода (алгоритм Крускала)

Задание - реализация алгоритма Крускала для вычисления минимальной суммарной длины дорожек в парке аттракционовЛимит времени - 5 секунд

188