Я был удивлен фактом это Map,?>
не a Collection>
.
Я думал, что это имело бы БОЛЬШОЙ смысл, если бы это было объявлено как таковое:
public interface Map extends Collection>
В конце концов, a Map
набор Map.Entry
,не так ли?
Так существует ли серьезное основание, почему оно не реализовало как таковой?
Благодаря Cletus для самого авторитетного ответа, но я все еще задаюсь вопросом, почему, если можно уже просмотреть a Map
как Set
(через entrySet()
), это только расширяет тот интерфейс вместо этого.
Если a
Map
aCollection
, каковы элементы? Единственным разумным ответом являются "Пары"ключ-значение""
Точно, interface Map
было бы большим!
но это обеспечивает очень ограниченный (и не особенно полезное)
Map
абстракция.
Но если это так затем, почему entrySet
указанный интерфейсом? Это должно быть полезно так или иначе (и я думаю, что легко привести доводы в пользу того положения!).
Вы не можете спросить, что оценивает данный контурные карты, и при этом Вы не можете удалить запись для данного ключа, не зная то, что оценивает ее, отображается на.
Я не говорю это вот и все Map
! Это может и должно сохранить все другие методы (кроме entrySet
, который избыточен теперь)!
Из FAQ по проектированию API коллекций Java :
Почему карта не расширяет коллекцию?
Это было сделано намеренно. Мы считаем, что отображения не являются коллекциями, а коллекции не являются отображениями. Таким образом, Map не имеет смысла расширять интерфейс Collection (или наоборот ).
Если Карта является Коллекцией, каковы элементы ? Единственный разумный ответ - "пары ключ-значение", но этот предоставляет очень ограниченную (и не особенно полезную) абстракцию карты. Вы можете ' • спрашивать, какому значению сопоставляется данный ключ , и вы не можете удалить запись для данного ключа, не зная, какому значению он сопоставляется.
Можно создать коллекцию для расширения карты , но возникает вопрос: каковы ключи? На самом деле удовлетворительного ответа нет, а принуждение к нему приводит к неестественному интерфейсу.
Карты можно рассматривать как Коллекции (из ключей, значений или пар), и этот факт отражается в трех «Операциях просмотра Коллекции » на Картах ( keySet, entrySet и значения). Хотя, по принципу , список можно рассматривать как отображение индексов карты на элементы, у него есть неприятное свойство, которое удаляет элемент из Список изменяет ключ, связанный с каждым элементом перед удаленным элементом. Вот почему у нас нет операции просмотра карты для списков.
Обновление: Думаю, цитата отвечает на большинство вопросов. Стоит подчеркнуть, что набор записей не является особенно полезной абстракцией. Например:
Set<Map.Entry<String,String>>
разрешит:
set.add(entry("hello", "world"));
set.add(entry("hello", "world 2");
(при условии, что метод entry ()
создает карту .Entry
instance)
Map
s требуют уникальных ключей, так что это нарушит это. Или, если вы вводите уникальные ключи в Set
записей, это не совсем Set
в общем смысле. Это набор
с дополнительными ограничениями.
Можно предположить, что отношение equals ()
/ hashCode ()
для Map.Entry
связано исключительно с ключом, но даже с этим есть проблемы. Что еще более важно, действительно ли это добавляет ценности? Вы можете обнаружить, что эта абстракция не работает, как только вы начнете рассматривать угловые случаи.
Стоит отметить, что HashSet
фактически реализован как HashMap
, а не наоборот. Это чисто деталь реализации, но, тем не менее, интересная.
Основная причина существования entrySet ()
состоит в том, чтобы упростить обход, чтобы вам не приходилось обходить ключи, а затем выполнять поиск ключа. Не воспринимайте это как очевидное доказательство того, что Карта
должна быть Набором
записей (imho).
Точно,
interface Map
было бы здорово!extends Set >
На самом деле, если бы реализует Map
, то я склонен согласиться .. Это кажется даже естественным. Но это не очень хорошо работает, правда? Допустим, у нас есть HashMap реализует Map
, LinkedHashMap реализует Map
и т.д ... это все хорошо, но если у вас есть entrySet ()
, никто не забудет реализовать этот метод, и вы можете быть уверены, что можете получить entrySet для любой карты, тогда как вы этого не делаете, если надеетесь, что разработчик реализовал оба интерфейса ...
Причина, по которой я не хочу иметь интерфейс Map
- это просто, потому что методов будет больше. А ведь это разные вещи, правда? Также очень практично, если я попаду на карту .
в IDE, я не хочу видеть .remove (Object obj)
и .remove (запись Map.Entry
, потому что я могу ' t do нажмите ctrl + пробел, r, верните
и покончите с этим.
Думаю, почему субъективно.
В C #, я думаю, Dictionary
расширяет или, по крайней мере, реализует коллекцию:
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>,
ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>,
IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback
В Pharo Smalltak также:
Collection subclass: #Set
Set subclass: #Dictionary
Но есть асимметрия с некоторыми методами. Например, collect:
принимает ассоциацию (эквивалент записи), а do:
принимает значения. Они предоставляют другой метод keysAndValuesDo:
для перебора словаря по записи. Добавить:
принимает ассоциацию, но remove:
был «подавлен»:
remove: anObject
self shouldNotImplement
Таким образом, это определенно выполнимо, но приводит к некоторым другим проблемам, касающимся иерархии классов.
Что лучше, то субъективно.
Несмотря на то, что вы получили несколько ответов, которые достаточно прямо охватывают ваш вопрос, я думаю, что было бы полезно немного отступить и взглянуть на вопрос немного более общий. То есть не для того, чтобы конкретно смотреть на то, как написана библиотека Java, а на то, почему она написана именно так.
Проблема здесь в том, что наследование моделирует только один тип общности. Если вы выберете две вещи, которые кажутся «коллекционными», вы, вероятно, сможете выделить 8 или 10 вещей, которые у них общего. Если вы выберете другую пару «похожих на коллекцию» вещей, у них также будет 8 или 10 общих вещей, но это не будут те же 8 или 10 вещей, как первая пара.
Если вы посмотрите на дюжину или около того разных «коллекционных» вещей, практически каждая из них, вероятно, будет иметь что-то вроде 8 или 10 общих характеристик хотя бы с одной другой - но если вы посмотрите на то, что разделяют через каждый один из них у вас практически ничего не остается.
Это ситуация, когда наследование (особенно одиночное наследование) просто плохо моделируется.Нет четкой границы между тем, какие из них на самом деле являются коллекциями, а какие нет, но если вы хотите определить значимый класс Collection, вы застряли, оставив некоторые из них. Если вы оставите только несколько из них, ваш класс Collection сможет предоставить только довольно разреженный интерфейс. Если вы оставите больше, вы сможете сделать интерфейс более богатым.
Некоторые также используют вариант, в основном говоря: «этот тип коллекции поддерживает операцию X, но вам не разрешено ее использовать, производя от базового класса, определяющего X, но пытаясь использовать производный класс 'X терпит неудачу (например, выбрасывая исключение).
Это все еще оставляет одну проблему: почти независимо от того, какие классы вы не используете, а какие вставляете, вам придется провести жесткую грань между классами, в которые входят, и какими вне зависимости от того, где вы проведете эту линию, у вас останется четкое, довольно искусственное разделение между некоторыми вещами, которые довольно похожи.
Ответ Клетуса хороший, но я хочу добавить семантический подход. Объединять оба варианта не имеет смысла, представьте себе случай, когда вы добавляете пару ключ-значение через интерфейс коллекции, а ключ уже существует. Интерфейс карты допускает только одно значение, связанное с ключом. Но если вы автоматически удалите существующую запись с тем же ключом, коллекция после добавления будет иметь тот же размер, что и раньше, что очень неожиданно для коллекции.
Коллекции Java не работают. Отсутствует интерфейс Relation. Следовательно, Map extends Relation extends Set. Отношения (также называемые мульти-картами) имеют уникальные пары имя-значение. Карты (также известные как «Функции») имеют уникальные имена (или ключи), которые, конечно, сопоставляются со значениями. Последовательности расширяют Карты (где каждый ключ является целым числом> 0). Пакеты (или мульти-наборы) расширяют Карты (где каждый ключ является элементом, а каждое значение - это количество раз, которое элемент появляется в сумке).
Эта структура допускает пересечение, объединение и т. Д. Ряда «коллекций». Следовательно, иерархия должна быть такой:
Set
|
Relation
|
Map
/ \
Bag Sequence
Sun / Oracle / Java ppl - пожалуйста, сделайте это правильно в следующий раз. Спасибо.