Почему класс ArrayDeque не выходит из AbstractQueue?
Почему класс ArrayDeque определяется как
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable
а не как
public class ArrayDeque<E> extends AbstractQueue<E>
implements Deque<E>, Cloneable, Serializable
Если вы посмотрите на следующую диаграмму (в которой есть ошибки, отношение ArrayDeque к Set совершенно неверно) будет иметь смысл, что ArrayDeque будет наследоваться от AbstractQueue, поскольку он реализует интерфейс Queue косвенно через интерфейс Deque.
http://en.academic.ru/pictures/enwiki/67/Collection_Classes.jpg
2 ответа
Один из сопровождающих jsr166, размещенных в core- библиотеках OpenJDK:
Я вообще не считаю ArrayDeque очередью / деком. У нас просто есть две фундаментальные структуры данных (ArrayList (обычный массив с изменяемым размером) и ArrayDeque (круговой массив с изменяемым размером)), которые могут разумно реализовать List и Queue, а ArrayDeque может дополнительно реализовать Deque.
Расширение AbstractCollection и реализация Deque согласуются с этим представлением.
Это также консервативный шаг, поскольку он позволит будущим версиям ArrayDeque расширить AbstractList для реализации большей части интерфейса List. Это может произойти только в том случае, если считается законным и / или желательным реализовать оба списка и очереди из-за конфликтующих контрактов equals / hashCode.
ArrayDeque может использоваться как двусторонняя очередь, стек и связанный список. Я думаю, что это скорее дизайнерское решение. Здесь, в ArrayDeque, мы должны быть более конкретными при добавлении / удалении элементов. Например,
[ArrayDeque.java]
public boolean add(E e) {
addLast(e);
return true;
}
[AbstractQueue.java]
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
Так как deque имеет двойное окончание, нам нужно указать, где мы добавляем элемент.
Другим соображением дизайна может быть сокращение стека вызовов. Если вы унаследуете AbstractQueue, это увеличит стек вызовов функций без дополнительной выгоды.
Например.,
Сейчас,
add () -> addLast ()
Если он наследует AbstractQueue,
add () -> offer () -> offerLast () -> addLast ()
Кроме того, не наследуя AbstractQueue, мы можем повторно использовать небольшие фрагменты операций добавления, удаления для различных структур данных (очередь, стек и связанный список), реализованных в ArrayDeque.
Наконец, Джошуа Блох (автор этого API) знает лучше:)