本文共 8424 字,大约阅读时间需要 28 分钟。
Stack
和Vector
是父子关系,我们依旧从源码入手,期望能够对你有帮助,如果本文有理解不对的地方,请及时指正,谢谢您@since 1.0public class Vectorextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable{...}
//保存元素的数组protected Object[] elementData;//容量增量,就是数组按多少速度扩容,这里是2倍protected int capacityIncrement;//元素个数protected int elementCount;//最大容量,跟ArrayList一样的private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
public Vector() { this(10);}public Vector(int initialCapacity) { this(initialCapacity, 0);}public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement;}public Vector(Collection c) { elementData = c.toArray(); elementCount = elementData.length; if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, elementCount, Object[].class);}
跟之前的ArrayList的实现基本一致,所以就不再赘述
public synchronized boolean add(E e) { modCount++; add(e, elementData, elementCount); return true;}private void add(E e, Object[] elementData, int s) { if (s == elementData.length) elementData = grow(); elementData[s] = e; elementCount = s + 1;}
public void add(int index, E element) { insertElementAt(element, index);}public synchronized void insertElementAt(E obj, int index) { if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } modCount++; final int s = elementCount; Object[] elementData = this.elementData; if (s == elementData.length) elementData = grow(); //核心方法arrycopy,将要插入的位置挪出来 System.arraycopy(elementData, index, elementData, index + 1, s - index); elementData[index] = obj; elementCount = s + 1;}
//逻辑跟ArrayList中的完全一致,不再赘述public synchronized boolean addAll(int index, Collection c) { if (index < 0 || index > elementCount) throw new ArrayIndexOutOfBoundsException(index); Object[] a = c.toArray(); modCount++; int numNew = a.length; if (numNew == 0) return false; Object[] elementData = this.elementData; final int s = elementCount; if (numNew > elementData.length - s) elementData = grow(s + numNew); int numMoved = s - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); elementCount = s + numNew; return true;}
public boolean remove(Object o) { return removeElement(o);}public synchronized boolean removeElement(Object obj) { modCount++; //indexOf方法就跟之前介绍的node方法一致,根据元素找出其位置 int i = indexOf(obj); if (i >= 0) { removeElementAt(i); return true; } return false;}public synchronized void removeElementAt(int index) { //检查索引 if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } else if (index < 0) { throw new ArrayIndexOutOfBoundsException(index); } //j 就是要删除元素的位置 int j = elementCount - index - 1; if (j > 0) { System.arraycopy(elementData, index + 1, elementData, index, j); } modCount++; elementCount--; elementData[elementCount] = null; /* to let gc do its work */}
public synchronized E set(int index, E element) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); E oldValue = elementData(index); elementData[index] = element; return oldValue;}
public synchronized E get(int index) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index);}
publicclass Stackextends Vector {...}
//由于父类Vector中的属性都是protected修饰,所以本类的属性就是使用了继承下来的Vector类中的属性
public Stack() {}
自身的方法比较少,但是有些方法是直接调用了父类的默认实现,以提高代码的复用性,我们可以都来看一下
Stack:public E push(E item) { addElement(item); return item;}Vector:public synchronized void addElement(E obj) { modCount++; add(obj, elementData, elementCount);}
public synchronized E pop() { E obj; //Vector:size int len = size(); //Stack:peek obj = peek(); //Vector:removeElementAt之前有贴实现的源代码 removeElementAt(len - 1); return obj;}
public synchronized E peek() { Vector:size int len = size(); if (len == 0) throw new EmptyStackException(); Vector:elemenAt方法是将len-1位置上的数据返回但是不删除 return elementAt(len - 1);}
public synchronized int search(Object o) { //Vector:lastIndexOf,从0开始一直往后循环搜索,遇到第一个相等的返回相同元素的index int i = lastIndexOf(o); if (i >= 0) { return size() - i; } //代表不存在 return -1;}
ArrayDeque
ArrayDeque
底层是基于数组实现的,所以其性能也是很好的Queue代表队列的抽象,而Deque是其一个子类,其进一步扩充了Queue的方法,Deque就既可以实现栈又可以实现队列了,我们分别看一下其中的方法定义
Queue:boolean add(E e);boolean offer(E e);E remove();E poll();E element();E peek();
上面一些方法的作用和区别如下,摘自
add()和offer()都是向队列中添加一个元素。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false。因此就可以在程序中进行有效的判断remove() 和 poll() 方法都是从队列中删除第一个元素。如果队列元素为空,调用remove() 的行为与 Collection 接口的版本相似会抛出异常,但是新的 poll() 方法在用空集合调用时只是返回 null。因此新的方法更适合容易出现异常条件的情况。element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null。
然后是Deque的方法
void push(E e);E pop();void addFirst(E e);...
方法较多,但是我们从push和pop已经看出,Deque接口已经为我们定义了栈的操作,所以我们可以使用Deque的具体实现类来完成栈和队列的操作,我们在这使用的是ArrayDeque
public static void main(String[] args) throws Exception { Dequequeue = new ArrayDeque<>(); queue.offer("A"); queue.offer("B"); queue.offer("C"); System.out.println(queue.poll()); System.out.println(queue.poll()); System.out.println(queue.poll()); //ABC Deque stack = new ArrayDeque<>(); stack.push("A"); stack.push("B"); stack.push("C"); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.pop()); //CBA}
还有一种队列,是有序队列,如PriorityQueue
,下面是他的实现方法,既然是保证了元素的有序,那么添加进入的元素肯定是实现Comparable
接口的,这里所说的有序不是加入顺序,而是排列顺序,所以这个类就可以定制排序了,下面只是介绍一下使用方法,具体的分析我会跟ArrayDeque
一起写出来的.
PriorityQueuequeue = new PriorityQueue<>();queue.add(1);queue.add(10);queue.add(3);queue.add(7);//[1, 7, 3, 10]System.out.println(queue);int size = queue.size();for (int i = 0; i < size; i++) { //1 3 7 10 System.out.println(queue.poll());}
然后是定制排序
Comparatorcomparator = (x,y) -> - Integer.compare(x,y);
使用List集合的一些建议
转载地址:http://phixa.baihongyu.com/