java 集合之List

原创 2016年08月29日 16:31:06

list 接口的特点是:有序,有下标,元素可重复。

它的实现类有几种 ArrayList 和 LinkedList,我们先看一下ArrayList的实现

public class TestArrayList {
	public static void main(String[] args) {
		List<String> arrayList = new ArrayList<String>();
		arrayList.add("zhang3");
	}
}
首先我们先new 了一个ArrayList<String>() 用一个引用arrayList来接受,执行的到的时候我们看一下源码

/**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
/**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
原来直接创建了一个Object的空数组,长度为0,之后调用add方法的时候
/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
这个方法干了两件事,第一行代码看它注释,我们可以知道重新创建一个数组,长度+1,第二行代码是给这个数组的 size+1 下标赋值 ,我们进去看一下

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
现在继续进入 grow(minCapacity);这个方法

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
等追到这个方法,我们已经明白  其他就是创建了一个长度+1的数组,然后将数据copy过来,其实Arraylist的结构就是数组的结构,因为在数组结构中元素的存储空间是连续的因此通过下标很容易对元素进行定位,所以查询效率很好,相对应的插入和删除效率会低。

我在看一下linkedList这个实现类,LinkedList是链表结构,由多个节点组成,每个节点由3部分构成,元素,上一个节点对象,下一个节点对象,我们看一下源码

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    transient int size = 0;

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
    }
在LinkedList的成员变量中,有长度 size ,上一个节点对象 first, 下一个节点对象,这个类里面有个 静态成员内部类 

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;
        }
}
这是一个 节点的类,包含3个部分,元素,上个节点对象,下个节点对象。

List<String> linkedList = new LinkedList<String>();
linkedList.add("li4");
linkedList.add("wang5");
我们看一下代码,当new 出来一个LinkedList对象的时候,调用无参构造,初始化成员变量,size为0, first 和 last 只是进行声明,没有指向任何区域为 null

调用add方法

public boolean add(E e) {
       linkLast(e);
       return true;
}
/**
* Links e as last element.
*/
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
         modCount++;
}
Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
}
刚开始last 为null,l 引用也赋值为null,新建一个节点对象,调用它的有参构造,将 l 变量作为上个节点对象(prev)传入,下个节点对象(next)为null,将成员变量last赋值后,判断 如果是第一个节点,将上一个节点指向它自身,如果不是,将下一个节点指向它自身(注:这里l.next  l指向的实际已是新创建节点 newNode的地址)。

如果查询的时候,只能从头或者 尾一个个查到我们需要的元素,get(i)这个方法做过优化,例如如果集合一共有5个元素,我们要查第二个 就会从头开始,如果要查第四个会从尾开始

/**
     * Returns the element at the specified position in this list.
     *
     * @param index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
/**
     * Returns the (non-null) Node at the specified element index.
     */
    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;
        }
    }
所以,这个链式结构,增删要快,查询要慢。

最后还有一个vector实现类,这个实现类也是数组结构,它是jdk1.0遗留下来的vector为了保证线程安全,采用了重量级的实现方式,在vector所有的方法都设计为同步方法,这样多线程在访问同一个vector对象的时候不会产生同步问题,但牺牲了效率。

例如:

public void add(E e) {
            int i = cursor;
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.add(i, e);
                expectedModCount = modCount;
            }
            cursor = i + 1;
            lastRet = -1;
        }

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

JAVA集合map、list、set详解

  • 2017年11月03日 17:36
  • 4KB
  • 下载

Java 集合系列之 List总结(LinkedList, ArrayLis,vector,stack等使用场景和性能分析)

Java 集合系列之 List总结(LinkedList, ArrayLis,vector,stack等使用场景和性能分析)

易语言仿java集合 list map源码

  • 2016年08月27日 13:32
  • 10KB
  • 下载

Java基础-集合框架之List

前面简单介绍集合框架和迭代器,下面来了解下List List集合的特有功能概述 * void add(int index,E element) * E remove(int index) * E g...

Java集合框架总结之List接口的使用

List是开发过程中经常用到的接口,使用它可以有序的存储元素,List接口提供了很多方法来实现元素的CRUD操作。它有很多实现类,常见的有ArrayList、LinkedList、Vector,每个实...

Java List集合冒泡法排序的两种实现

冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java 集合之List
举报原因:
原因补充:

(最多只允许输入30个字)