【第22期】观点:IT 行业加班,到底有没有价值?

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、LinkedList)常用操作例子(基础必备)

package com.net.xinfang.reflect; import java.util.ArrayList; import java.util.Arrays; import java.u...

Java集合类List/Set/Map的区别和联系

一、Array ,Arrays Java所有“存储及随机访问一连串对象”的做法,array是最有效率的一种。 1、效率高,但容量固定且无法动态改变。 array还有一个缺点是,无法判断其中实际存有多少元素,length只是告诉我们array的容量。 2、Java中有一个A...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

Java集合框架List,Map,Set等全面介绍

Java Collections Framework是Java提供的对集合进行定义,操作,和管理的包含一组接口,类的体系结构。 Java集合框架的基本接口/类层次结构: java.ut...

I学霸官方免费教程三十一:Java集合框架之List集合

集合框架 在数组的使用过程中可以看到,想要向数组中插入元素和删除元素非常麻烦,而且数组的长度是无法改变的。java为我们提供了批量存储数据更加方便的容器,就是集合。 集合和数组的作用一样,都是为了使用一个变量来存储一批数据的;但集合使用起来更加方便,而且集合的长度是可以变化的。 List接口 ...

java基础:集合类型set,list,map

java集合的主要分为三种类型:Set(集)List(列表)Map(映射) 然而所有的集合都是基于数组来实现的,因为集合是对数组的封装,所以任何一个集合类型提供的功能都比数据高,但是效率都没有数组高...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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