【发布时间】:2018-10-20 09:14:35
【问题描述】:
我知道在 Java 中,LinkedList class implements both Deque and List 接口。
这让我有些困惑。
在计算机科学教学大纲中,我从未被告知队列可以是一个列表,或者更准确地说,队列可以表现得像一个列表。也就是说,列表可以做一些事情,但队列不能。但是该列表可以表现得像一个队列。比如List接口有the following methods:
add(E e)
add(int index, E element)
但是Queuehas only the following:
add(E e)
很明显Queue 不允许在特定索引处插入,而List 允许插入。与Queue.remove() 与List.remove(int index)、List.get(int index) 与Queue.peek() 等其他操作的情况相同。
也就是说,list 是一种更通用的数据结构,可以模拟Queue。
现在能够模拟与拥有合同子集不同。也就是说,Queue 不允许 List 的某些操作(索引)并且只允许以特定方式完成某些操作(仅在尾部插入并仅从头部移除)。所以Queue 并没有真正“添加”到List 的合同。这正是为什么Queue 没有在Java 集合框架中扩展List,而是都扩展Collection 接口的原因。我相信这也是为什么任何类都实现两者都不正确的原因,因为Queue 的合同与List 的合同冲突(这就是为什么他们分别从Collection 接口分叉出来的原因)。但是,LinkedList 实现了这两个接口。
我也遇到过this 回答:
LinkedList实现恰好满足Deque契约,那么为什么不让它实现接口呢?
我仍然不明白我们怎么说“LinkedList 实现恰好满足Deque 合同”。队列的概念不允许在任意索引处插入。因此,Queue 接口没有这样的方法。
但是,我们只能通过接口强制执行合同,不能禁止某些方法的实现。作为列表(名称中有“List”),我觉得在LinkedList 中有队列方法peek()、pop() 和add(int index, E element) 是不正确的。
我相信,相反我们应该有单独的类LinkedQueue,它可以有队列的链接实现,类似于LinkedBlockingQueue,它包含BlockingQueue 的链接实现。
还要注意LinkedList 是唯一继承自列表和队列家族的类,也就是说,没有其他类同时实现List 和Queue (AFAIK)。这是否表明LinkedList 做得不好?
我是不是完全错了,而且是在不必要地思考?
【问题讨论】:
-
Linked List 实现了 Deque 和 List。这并不意味着 Deque 是一个列表。相反,Deque 和 List 都可以实现为 Linked List。
-
当前编写的
LinkedList的数据结构代表所有这些接口的有效实现。因此,很自然地宣布它是所有这些。你的第一段错了。Queue实际上没有List拥有的方法。但这就是为什么我们没有Queue implements List。LinkedList是它们两者,这并不意味着Queue现在是List。 -
这个问题问得很好,所以请投我赞成票。不知道为什么人们会拒绝投票,可能是因为他们认为这愚蠢(但这不是拒绝投票的正当理由)。
-
任何接口都不会阻止实现支持更多操作。 (除非重载方法发生冲突)
-
答案是说你没有抓住重点,但我认为你是绝对正确的。做
class A implements B, C并不意味着A可以被认为是B或C,它意味着它同时是B和C。这里有一个队列类型的violated invariant(你不能修改中间的元素),所以它是不正确的子类型。应该有的实际参数是“队列是否要求元素不能在中间修改或仅在 FIFO 中可以在末端修改”。
标签: java collections