Properties

因为这个和 IO 的流输入流输出有关,所以日后再来补坑。

Queue

首先来看看 Queue 接口:

1
public interface Queue<E> extends Collection<E>

这里可以看到是和 List 同级别的接口,都继承了 collection,顾名思义啊,这个 Queue 就是一个实现了队列功能的集合,First In First Out 先进先出。

而在 Java 中,实现 Queue 接口的类是:LinkedList,虽说它叫作 LinkedList ,但是它实际上是实现了 List 和 Queue 两个接口。我们可以向上转型为 Queue,然后把它当作队列的实例使用。

看一看 Queue 里面封装的方法:

1
2
3
4
5
6
boolean add(E e); //向队列尾部加入元素
boolean offer(E e); //向队列尾部加入元素
E remove(); //返回队头元素,并删除
E poll(); //返回队头元素,并删除
E element(); //返回队头元素,但不删除
E peek(); //返回队头元素,但不删除

上面相同的功能有两种不同的方法实现,一个是常用词(add,remove,element),另一个是非常用词(offer,poll,peek),两者的区别就是前者出错时直接抛出异常,后者时返回 null。

PriorityQueue

优先队列,在 Java 中使用堆结构实现。为 PriorityQueue 类,并实现了 Queue 接口。其所拥有的的方法和 Queue 差不多,唯一的不同是队列开头的元素是按照自己要求排出来的第一。

因为涉及到了比较,所以和 TreeMap 以及 Collections.sort() 一样,要么在元素的类中实现 Comparable 接口中的 compareTo() 方法,要么在建立 PriorityQueue 实例的时候传入一个 Comparator 的匿名类进去。

Deque

Deuqe 是个双端队列,双端队列故名思意就是可以在队列头和队列尾都添加元素的队列,同样是实现了FIFO先进先出的特性。ArrayDeque 和 LinkedList 两者实现了 Deque 接口(好家伙 LinkedList 也太全能了吧),而 Deque 接口规定了必须要实现的方法:

功能 Deque
添加元素到队尾 addLast(E e) / offerLast(E e)
取队首元素并删除 E removeFirst() / E pollFirst()
取队首元素但不删除 E getFirst() / E peekFirst()
添加元素到队首 addFirst(E e) / offerFirst(E e)
取队尾元素并删除 E removeLast() / E pollLast()
取队尾元素但不删除 E getLast() / E peekLast()

用法和优先队列的 Queue 完全相同,而且 Deque 也是继承于 Queue 接口的。

1
public interface Deque<E> extends Queue<E>

所以 Deque 也可以使用 offer() 添加元素到队尾,但是并不推荐这样写,对于这种双端队列,还是写成 offerLast() 这样更明确一些。

因为像 LinkedList 这样实现了很多不同接口的类,我们具体要把它当作某一个接口使用的时候,因该让它向上转型为对应的接口,然后按照接口拥有的功能进行操作,这种尽量持有接口的方法才是面向对象的思想。

Stack

众所周知,栈是一个先进后出的数据结构,和叠碗筷差不多。在 Java 中并没有单独搞一个叫作 Stack 的接口,这是因为历史遗留问题,有一个单独叫作 Stack 的类,因为这个 Stack 类所拓展的 Vector 类是一个早期 Java 写的一个不太行的类,里面很多方法都是线程安全的,速度很慢,所以就直接废弃不用了。

那如何实现栈结构呢?当然是使用万能的双端队列 Deque 啦,Deque 接口就封装了栈所需要的一些方法,如:

  • 把元素压入栈中: push(E)/addFirst(E)
  • 把元素弹出栈:pop(E)/removeFirst(E)
  • 取栈顶元素但不弹出: peek(E)/peekFirst(E)

如果将 Deque 当作 Stack 使用的时候,尽量用 push pop peek 这样的方法,更直接清晰。

栈数据结构的用途非常多,以后会慢慢学的。