Лучше использовать Список или Набор?

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

public List<SomeDataType> getData() {
   return this.data;
}

public void setData(List<SomeDataType> data) {
   this.data = data;
}

Это означает, что я позволил внутренним деталям реализации просачиваться? Я должен делать это вместо этого?

public Collection<SomeDataType> getData() {
   return this.data;
}

public void setData(Collection<SomeDataType> data) {
   this.data = new ArrayList<SomeDataType>(data);
}
36
задан Vivin Paliath 26 May 2010 в 23:46
поделиться

8 ответов

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

25
ответ дан 27 November 2019 в 05:51
поделиться

При возврате реализации интерфейса или класса, который находится в высокой иерархии, эмпирическое правило состоит в том, что объявленный тип возвращаемого значения должен быть ВЫСОКИМ уровнем, который обеспечивает минимальную функциональность, которую вы подготовили. чтобы гарантировать вызывающему абоненту, и что вызывающему абоненту разумно необходимо. Например, предположим, что вы действительно возвращаете ArrayList. ArrayList реализует List и Collection (среди прочего). Если вы ожидаете, что вызывающей стороне потребуется использовать функцию get (int x), тогда не получится вернуть Collection, вам нужно будет вернуть List или ArrayList. Пока вы не видите причин, по которым вы могли бы когда-либо изменить свою реализацию, чтобы использовать что-то другое, кроме списка - скажем, Set, - тогда правильный ответ - вернуть List. Я не уверен, есть ли в ArrayList какая-либо функция, которой нет в List, но если есть, применимы те же рассуждения. С другой стороны, как только вы вернете List вместо Collection, вы теперь в некоторой степени заблокированы в своей реализации. Чем меньше вы вкладываете в свой API, тем меньше ограничений вы накладываете на будущие улучшения.

(На практике я почти всегда возвращаю Список в таких ситуациях, и он никогда не сжигал меня. Но мне, вероятно, действительно стоит вернуть Коллекцию.)

8
ответ дан 27 November 2019 в 05:51
поделиться

Использование наиболее общего типа, которым является Коллекция, имеет наибольший смысл, если нет явной причины использовать более конкретный тип - Список. Но что бы вы ни делали, если это API для публичного использования, четко укажите в документации, что он делает; если он возвращает неглубокую копию коллекции, скажите так.

5
ответ дан 27 November 2019 в 05:51
поделиться

Это зависит от того, какие гарантии вы хотите предоставить пользователю. Если данные являются последовательными, так что порядок элементов имеет значение и вы разрешаете дублирование, используйте список. Если порядок элементов не имеет значения, а дублирование может или не может быть разрешено, используйте коллекцию. Поскольку вы фактически возвращаете базовую коллекцию, у вас не должно быть одновременно функции get и set, только функции get, поскольку возвращаемая коллекция может быть видоизменена. Кроме того, предоставление функции set позволяет пользователю изменять тип коллекции, тогда как вы, вероятно, хотите, чтобы конкретный тип контролировался вами.

0
ответ дан 27 November 2019 в 05:51
поделиться

Да, ваша первая альтернатива дает утечку деталей реализации, если это не часть вашего интерфейсного контракта, что метод всегда будет возвращать список. Кроме того, позволять пользовательскому коду заменять экземпляр вашей коллекции несколько опасно, потому что реализация, которую они передают, может вести себя не так, как вы ожидаете.

Конечно, все зависит от того, насколько вы доверяете своим пользователям. Если принять философию Python о том, что «мы все здесь взрослые по согласию», то первый метод подойдет. Если вы думаете, что ваша библиотека будет использоваться неопытными разработчиками, и вам нужно сделать все возможное, чтобы «присмотреть» за ними и убедиться, что они не делают что-то неправильное, тогда предпочтительнее не позволять им устанавливать коллекцию и даже не возвращать актуальная коллекция. Вместо этого верните (неглубокую) копию.

1
ответ дан 27 November 2019 в 05:51
поделиться

Если бы я был озабочен тем, чтобы скрыть внутреннее представление моих данных от внешнего пользователя, я бы использовал либо XML, либо JSON. В любом случае они довольно универсальны.

-1
ответ дан 27 November 2019 в 05:51
поделиться

Независимо от возможности индексирования в список через List.get (int), ожидают ли пользователи (или вы), что элементы коллекции находятся в надежном и предсказуемый порядок? Может ли коллекция содержать несколько экземпляров одного и того же предмета? Оба они являются ожиданиями списков, которые не являются общими для более общих коллекций. Это тесты, которые я использую при определении того, какую абстракцию предоставить конечному пользователю.

9
ответ дан 27 November 2019 в 05:51
поделиться

Возврат списка соответствует программированию на наиболее подходящем интерфейсе.

Возврат коллекции может вызвать неоднозначность для пользователя, поскольку возвращаемая коллекция может быть либо набором, либо списком, либо очередью.

18
ответ дан 27 November 2019 в 05:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: