JAVA自带的各种Queue

1、LinkedList

有人可能会问,这货怎么还是个Queue?

实际上LinkedList不仅实现了List,还实现了Deque,而Deque继承自Queue。

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

我们知道队列的特性,先进先出,而Deque定义为双端队列,即队首队尾都有出入口,可以实现双端出入。

操作就不看了,很简单的链表操作。

2、PriorityQueue

看名字就知道,这是一个有优先级的队列,我们来看看它的内部定义:

public class PriorityQueue<E> extends AbstractQueue<E>
    implements java.io.Serializable {
	//默认容量
    private static final int DEFAULT_INITIAL_CAPACITY = 11;
    /**
     * Priority queue represented as a balanced binary heap: the two
     * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The
     * priority queue is ordered by comparator, or by the elements'
     * natural ordering, if comparator is null: For each node n in the
     * heap and each descendant d of n, n <= d.  The element with the
     * lowest value is in queue[0], assuming the queue is nonempty.
     */
    transient Object[] queue; // 用数组保存元素
    int size;
    private final Comparator<? super E> comparator;
    public PriorityQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }
    public PriorityQueue(Comparator<? super E> comparator) {
        this(DEFAULT_INITIAL_CAPACITY, comparator);
    }
    public PriorityQueue(int initialCapacity,
                         Comparator<? super E> comparator) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.queue = new Object[initialCapacity];
        this.comparator = comparator;
    }
	...省略其他代码
}

从上面我们可以知道,这是一个平衡二叉树结构的队列,且其父节点都比叶子节点小,类似下图结构

而且我们根据上图可以得到如下结论:

  1. 左子节点的下标 = 父节点下标*2+1
  2. 右子节点的下标 = 父节点下标*2+2
  3. 父节点下标 = (子节点-1)/2

来看一下它的入队操作:

public boolean offer(E e) {
    if (e == null)
        throw new NullPointerException();
    modCount++;
    int i = size;
    if (i >= queue.length)
        grow(i + 1); //扩容,长度小于64为原来的两倍,反之为原来的150%
    siftUp(i, e);
    size = i + 1;
    return true;
}

private void siftUp(int k, E x) {
    if (comparator != null) //比较器为空
        siftUpUsingComparator(k, x, queue, comparator); //对比用了comparator,其他和siftUpComparable一致
    else
        siftUpComparable(k, x, queue);
}

private static <T> void siftUpComparable(int k, T x, Object[] es) {
    Comparable<? super T> key = (Comparable<? super T>) x;
    while (k > 0) {
        int parent = (k - 1) >>> 1;  //找到其父节点下标
        Object e = es[parent]; 
        if (key.compareTo((T) e) >= 0) //对比,大于就结束
            break;
        es[k] = e; //把父元素往下移
        k = parent; //继续同上对比
    }
    es[k] = key;
}

出队操作有两种,一种是移除数根元素,一种是移除任意位置元素,都涉及到元素移动的操作

详情请移步https://www.cnblogs.com/CarpenterLee/p/5488070.html

3、ArrayDeque

内部使用循环数组来实现双端队列,分别定义了head和tail用于指向队首队尾在数组中的下标。

public class ArrayDeque<E> extends AbstractCollection<E>
    implements Deque<E>, Cloneable, Serializable{
	
	transient Object[] elements; //存储元素
    transient int head; //队首下标
    transient int tail; //队尾下标
    
}

其中有两个很重要的方法,涉及到头尾下标的移动,入队出队的操作就是依赖这两个方法来移动头尾下标

/**
 * Circularly increments i, mod modulus.
 * Precondition and postcondition: 0 <= i < modulus.
 */
static final int inc(int i, int modulus) { //循环递增
    if (++i >= modulus) i = 0; //大于数组长度就归零
    return i;
}

/**
 * Circularly decrements i, mod modulus.
 * Precondition and postcondition: 0 <= i < modulus.
 */
static final int dec(int i, int modulus) { //循环递减
    if (--i < 0) i = modulus - 1; //小于零就设置为数组最后一位
    return i;
}

ArrayDeque也有两种迭代器实现,分别按队列的两端顺序遍历

public Iterator<E> iterator() {
    return new DeqIterator();
}

public Iterator<E> descendingIterator() {
    return new DescendingIterator();
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值