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集合系列——List集合之ArrayList介绍(二)

List是 java.util包下面的类,从 java集合系列——java集合概述(一) 中可以知道,List继承了Collection 接口! List本身也是一个接口,它的实现有ArrayLis...
  • u010648555
  • u010648555
  • 2017年02月26日 16:06
  • 1648

java List集合记录 ArrayList和LinkedList的区别

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 2.对于元素的查找,ArrayList觉得优于LinkedList,因为LinkedList要移动指针...
  • buzaiguihun
  • buzaiguihun
  • 2016年07月04日 23:22
  • 786

java集合系列——List集合总结(六)

List继承了Collection,是有序的列表。 实现类有ArrayList、LinkedList、Vector、Stack等 ArrayList是基于数组实现的,是一个数组队列。可以动态的增加容...
  • u010648555
  • u010648555
  • 2017年03月02日 21:46
  • 834

Java基础之List集合原理(一)

1.我们都知道,Java基础里面有一块知识非常重要,在我们的开发中也是经常使用,这块知识就是集合,那么我们回顾一下集合的层级结构 从图中我们看到了集合的顶层是Collection接口,可以理解为这是...
  • u011692041
  • u011692041
  • 2015年11月14日 19:26
  • 2910

Java集合面试总结

★★★★★集合框架:用于存储数据的容器。 特点: 1:对象封装数据,对象多了也需要存储。集合用于存储对象。 2:对象的个数确定可以使用数组,但是不确定怎么办?可以用集合。因为集合是可变长度的。  ...
  • CSDN_Terence
  • CSDN_Terence
  • 2017年10月28日 22:01
  • 263

Java_集合操作_清空list

package test; import java.util.ArrayList; import java.util.List; public class test { public stat...
  • u012552052
  • u012552052
  • 2015年01月29日 17:44
  • 2905

《Java源码解析》集合框架List之ArrayList

Java的集合框架的底层实现在面试中用的比较多,接下来我就用一些时间来分析一下Java的集合框架中的List(ArrayList,LinkedList),Set(Set的各种实现类),Map(Hash...
  • u010853261
  • u010853261
  • 2016年12月20日 09:47
  • 463

java List集合分页

分页内容全部显示 import java.util.ArrayList; import java.util.List; public class Sublist { ...
  • zwyjg
  • zwyjg
  • 2017年05月12日 17:28
  • 1486

Java集合&List的实现

一.java集合类图如下所示:    上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,Ab...
  • u012658346
  • u012658346
  • 2016年03月21日 17:06
  • 1782

java集合系列——List集合之Stack介绍(五)

Stack的简介Stack 类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 pe...
  • u010648555
  • u010648555
  • 2017年03月02日 21:40
  • 1150
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java 集合之List
举报原因:
原因补充:

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