3

为什么类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 继承是有道理的,因为它通过 Deque 接口间接实现了 Queue 接口。

在此处输入图像描述
(来源:academic.ru

4

2 回答 2

2

在OpenJDK core-libs上发布的 jsr166 维护者之一:

我根本不认为 ArrayDeque 是一个队列/双端队列。我们这里只有两个基本的数据结构(ArrayList(普通可调整大小数组)和ArrayDeque(循环可调整大小数组)),它们都可以以合理的方式实现List和Queue,ArrayDeque还可以额外实现Deque。

扩展 AbstractCollection 并实现 Deque 与该观点一致。

这也是一个保守的举动,因为它将允许 ArrayDeque 的未来版本扩展 AbstractList以实现大部分 List 接口。仅当由于冲突的 equals/hashCode 合同而被认为是合法的和/或需要同时实现 List 和 Queue时才会发生这种情况。

于 2014-12-24T16:23:13.017 回答
1

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");
    }

由于双端队列是双端的,我们需要明确添加元素的位置。

另一个设计考虑可能是减少调用堆栈。如果继承 AbstractQueue,它会增加函数调用堆栈而没有额外的好处。

例如。,

现在,

add() -> addLast()

如果它继承了AbstractQueue,

add() -> offer() -> offerLast() -> addLast()

此外,通过不继承 AbstractQueue,我们能够重用在 ArrayDeque 中实现的不同数据结构(队列、堆栈和链表)的小块添加、删除操作。

最后,Joshua Bloch(这个 API 的作者)知道得更好 :)

于 2014-09-15T15:58:46.737 回答