Почему интерфейс Java List не поддерживает getLast ()? - PullRequest
18 голосов
/ 26 июня 2009

Я пытаюсь понять несоответствие API в библиотеке стандартных коллекций Java.

В List или AbstractList нет метода для получения последнего элемента, хотя можно смоделировать его с помощью size и getIndex ().

Однако LinkedList поддерживает эту функцию.

Есть идеи, почему было решено не поддерживать этот метод в интерфейсе?

Ответы [ 7 ]

19 голосов
/ 26 июня 2009

Интерфейс java.util.List не поддерживает getLast(), потому что дизайнеры выбрали «минимальный интерфейс». Благодаря минимальному количеству определенных методов это облегчает понимание и ускоряет изучение.

Это отличается от «гуманного интерфейса» (такого как используемый в классе массива Ruby ), который пытается предоставить методы для выполнения общих операций (например, getLast()). Поскольку существует много применений, к которым может быть применено такое фундаментальное понятие, как список, это приводит к гораздо более широким интерфейсам.

Для получения дополнительной информации см. Минимальный интерфейс Мартина Фаулера и Гуманный интерфейс описания.

Относительно того, почему LinkedList поддерживает getLast() и т. Д., Чтобы процитировать Javadoc:

... класс LinkedList предоставляет методы с одинаковыми именами для получения, удаления и вставки элемента в начале и конце списка. Эти операции позволяют использовать связанные списки в качестве стека, очереди или двусторонней очереди (deque).

Предположительно было высказано мнение, что общий Список не подходит для этих конкретных случаев использования.

В качестве идеи главного дизайнера API коллекций Java (Джошуа Блоха) он предоставляет этот список принципов разработки API , по которым он работает. Из которых наиболее актуальными для этого вопроса являются:

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

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

Держите API свободными от деталей реализации. Они вводят пользователей в заблуждение и мешают им развиваться. Не всегда очевидно, что является деталью реализации: остерегайтесь чрезмерного уточнения.

Минимизировать доступность; если сомневаешься, сделай это приватным. Это упрощает API и уменьшает связь.

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

Однако он также заявляет:

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

Это просто показывает, что рекомендации по проектированию часто конфликтуют, и самая сложная часть работы разработчиков API - это сбалансировать эти конфликты.

5 голосов
/ 26 июня 2009

Обычно причина в том, что они хотели указать каждую функцию с требованием Big-O и считали, что getLast () не может быть эффективно реализован во всех списках. Таким образом, они вводят это на каждом уровне со своим обещанием Big-O.

Или это мог быть просто недосмотр, или они чувствовали, что это недостаточно распространено, и если вам это нужно, вы можете получить его с помощью size / getIndex.

2 голосов
/ 26 июня 2009

Цель интерфейса - обеспечить максимальное удобство использования с минимально возможным количеством открытых методов. Чем меньше методов поддержки, тем лучше. Как вы сказали, метод getLast () не существует, потому что он может быть получен.

LinkedList, с другой стороны, является конкретной реализацией и поэтому не имеет этих проблем.

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

1 голос
/ 26 июня 2009

Метод getLast () взят из интерфейса Deque, который реализует LinkedList. Если вам нужна версия с массивной поддержкой, вы можете использовать ArrayDeque. Я предполагаю, что он не является частью интерфейса List, потому что они хотели отделить различные абстрактные типы данных в отдельные интерфейсы, даже если такая реализация, как LinkedList, может реализовать более одного интерфейса.

1 голос
/ 26 июня 2009

Как вы сказали, с помощью List вы можете получить последний с помощью getIndex (), поскольку он основан на индексах. Поэтому лично я не вижу веских оснований для этого (поскольку вы можете написать это сами).

Хотя LinkedList не основан на массивах, поэтому индексов нет, имеет смысл предоставить такой метод, иногда вам нужно знать последний элемент.

0 голосов
/ 26 июня 2009

В интерфейсе List нет удобных методов такого типа. Нет getFirst () или getLast (). Это строго на основе индекса. LinkedList нужен способ избежать поиска на основе индекса, если это возможно по соображениям производительности, поэтому getLast - это на самом деле оптимизация, а не метод удобства.

Я уверен, что дизайнеры хотели уменьшить количество методов, поэтому они не добавили много потенциально удобных методов.

0 голосов
/ 26 июня 2009

getLast () не может быть реализовано в одностороннем связанном списке. Функция getIndex () в одностороннем связанном списке, вероятно, будет сканировать весь список с самого начала, поэтому это влияет на эффективность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...