JAVA_list总结

list,列表序列。是编程工作充常用的对象,类似数组,用于存储统一类型的集合的对象。
先放结论:

类型数据结构特点描述
ArrayList数组最常用,随机访问高效,插入删除效率低
LinkedList双向链表随机访问效率低,但随机插入、随机删除效率低
Vector数组类似ArrayList,但线程安全
Stack它继承于Vector,先进后出

ArrayList

首先,ArrayList的本质是数组,在jdk1.8.0_121的java.util.ArrayList中,可以看到以下代码

transient Object[] elementData; // non-private to simplify nested class access

这就是ArrayList的本质,一个Object[],只不过,在add的时候,会自动的进行扩容而已。

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

也因此:

  1. 随机访问效率高(直接elementData[i]就可以取得对象)
  2. 插入删除慢(每次插入删除,尤其是对非尾对象进行改变时,都会导致Object[] elementData结构整个的变动)
  3. 线程不安全(单纯的数组,没有做任何保护处理)

推荐使用方法:

// ArrayList基本例子
List<String> arrayList = new ArrayList<String>();
arrayList.add("test1");
arrayList.add("test2");
arrayList.add("test3");
for (int i = 0; i < arrayList.size();i++){
    System.out.println(arrayList.get(i));
}

LinkedList

源码(jdk1.8.0_121):

transient Node<E> first;

transient Node<E> last;

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

是的,这就是双向链表,只保存首尾两个节点,同时,每个节点保存其自身前后节点地址。也因此:

  1. 访问效率低(非首尾节点时,只能从首尾节点开始,一个一个去寻找)
  2. 插入删除效率高(只需要创建或者删除节点,并且调整相邻节点的地址即可)
  3. 线程不安全(节点,没有做任何保护处理)

推荐使用方法:

// linkedList基本例子
List<String> linkedList = new LinkedList<String>();
linkedList.add("test1");
linkedList.add("test2");
linkedList.add("test3");
for (String data : linkedList){
    System.out.println(data);
}

另外,用于LinkedList的implements包含Deque,而Deque继承Queue,所以LinkedList也可作为队列来使用。
例子:

Queue<String> queue = new LinkedList<String>();
queue.add("test1");
queue.add("test2");
queue.add("test3");
System.out.println(queue.size());
for (int i = 0; i < 3;i++){
    System.out.println(queue.poll());
}
System.out.println(queue.size());
// 结果:
// 3
// test1
// test2
// test3
// 0

Vector

源码(jdk1.8.0_121):

protected Object[] elementData;

是的,和ArrayList一样,Vector的本质是一个数组,区别在于相关的方法:

public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}

对,重点就是synchronized,因为Vector的方法都有synchronized,有了线程的保护,所以Vector是线程安全的。
Vector类似ArrayList,是线程安全的。知道这一点就足够了。

** !但是! **
虽然Vector是线程安全的,但是想要使用线程安全的ArrayList的时候,简易使用JUC集合类中的CopyOnWriteArrayList。

Stack

源码(jdk1.8.0_121):

protected Object[] elementData;

又来?是的,Stack的底层仍然是一个数组,但是相关的方法却大不一样。虽然由于继承父类Vector,add这种方法还是存在,但是却一般不用。一般使用的是以下方法:

public E push(E item) {
    addElement(item);

    return item;
}
public synchronized E pop() {
    E       obj;
    int     len = size();

    obj = peek();
    removeElementAt(len - 1);

    return obj;
}
public synchronized E peek() {
    int     len = size();

    if (len == 0)
        throw new EmptyStackException();
    return elementAt(len - 1);
}

说明:
push:将元素推入栈中,通过将元素追加的数组的末尾中。
peek:取出栈顶元素,不执行删除,返回数组末尾的元素。
pop:取出栈顶元素,将该元素从栈中删除,返回
总之:

  1. 使用push插入,用peek或pop去除(符合堆栈特性)
  2. 线程安全(使用synchronized)

例子:

// stack基本例子
Stack<String> stack = new Stack<String>();
stack.push("test1");
stack.push("test2");
stack.push("test3");
for (int i = 0; i < 3;i++){
    System.out.println(stack.pop());
}
    原文作者:常烦常乐
    原文地址: https://www.cnblogs.com/changfanchangle/p/8867445.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞