JAVA集合面面观

Posted ywd979

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA集合面面观相关的知识,希望对你有一定的参考价值。

List的常用实现:vector,ArrayList,linkedList。

总体关系如下(java8):
技术分享图片

vector和arraylist

两者底层都是采用数组的形式。但是有些许不同

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

// vector
protected Object[] elementData;
  • 在序列化的时候,arraylist将会调用writeObject和readObject方法来序列化。所以比vector在序列化上更安全。
  • 其次,vector的主要元素操作方法都是synchronize修饰的来保证线程安全。(现在基本抛弃vector。代替Collections.synchronizeList的方法来构造线程安全)
  • vector的构造函数允许扩展的步长。
arraylist和linkedlist

arraylist底层是数组实现
linkedlist是链式的线性表,也是双向链表,因为从上图可以看到它还实现了Deque,可以用做双端队列,或者栈使用。

arraylist是数组实现,所以对于修改List的操作,会进行整体的搬家。

public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

可以看出,对于修改数据的操作,会非常重。但是相对于get将非常快。直接操作下标获取。

public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }
E elementData(int index) {
        return (E) elementData[index];
    }

linkedlist,由内部类node实现。有前后节点组成双向链表

 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;
        }
    }

看实现可以知道。当修改元素的时候,只需要修改节点对应的前节点和后节点就能完成插入。

public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }
void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

然后看get, 需要从头或者从末开始遍历。

public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

另外linkedlist实现了Deque。提供的几个方法,所以可以作为队列使用。
技术分享图片

// 待续




以上是关于JAVA集合面面观的主要内容,如果未能解决你的问题,请参考以下文章

laravel特殊功能代码片段集合

201621123062《java程序设计》第九周作业总结

Java方法

金蝶handler中 collection 代码片段理解

Alfred常见使用

比较 C# 中的字符串片段并从集合中删除项目