Подтвердить что ты не робот

Почему интерфейс Java List не поддерживает getLast()?

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

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

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

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

4b9b3361

Ответ 1

Интерфейс java.util.List не поддерживает getLast(), потому что дизайнеры пошли на "минимальный интерфейс". С минимальным количеством методов, которые он определяет, он упрощает понимание и ускорение обучения.

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

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

Что касается того, почему LinkedList поддерживает getLast() и т.д., чтобы процитировать javadoc:

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

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

Как понимание ума главного дизайнера API Java Collections (Joshua Bloch), он предоставляет этот список шаблонов дизайна API который он работает. Из них наиболее уместными в этом вопросе являются:

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

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

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

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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