`
qq7689791
  • 浏览: 9743 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java源码分析之List接口以及ArrayList、LinkedList、Stack、Vector等实现类

 
阅读更多

讲解jdk源码中List接口之前我们先来看一个模式,迭代器设计模式。

        迭代器设计模式主要是为了对容器提供统一的遍历接口,对于不同的数据结构的遍历方式由不同的iterator实现类所实现,而且也对原始数据进行了封装,不至于在用户使用时暴漏内部细节,类图如下。

 上面图中的各个类其实就是jdk中Collection容器对迭代器设计模式的一个实现,Itr是AbstractList的一个内部类,内部类的好处就是它可以直接访问AbstractList中的数据,Itr类实现了对元数据的遍历,部分代码如下。

public boolean hasNext() {
    return cursor != size();
}

public E next() {
    checkForComodification();
    try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
    } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
    }
}

        java中的List接口以及实现类,类图如下:

List中主要有2种数据结构的实现,一种是数组,另一种是链表。

    数组的实现有ArrayList、Vector、Stack、CopyOnWriteArrayList他们都继承了AbstractList,AbstractList实现了List中的部分接口,并且实现了数组结构的遍历,也就是上边说到的迭代器设计模式中Iterator部分,Stack实现了一个LIFO,Vector实现了线程安全,CopyOnWriteArrayList则是线程安全的一个变体,读的操作没有锁性能会更好,而写的时候存在锁并且在写的时候copy元数据,在新的数据上做修改,然后在同步回元数据,从而实现了在遍历的时候可以对其进行修改而不会抛出CurrentModificationException异常。基于数组实现的容器都实现了RandomAccess接口,这是一个空接口,实现了这个接口的类代表支持随机访问,而支持随机访问的类在遍历时正如RandomAccess类中描述的那样,上面的遍历方式性能会好于下面的遍历方式如下:

 * <pre>
 *     for (int i=0, n=list.size(); i &lt; n; i++)
 *         list.get(i);
 * </pre>
 * runs faster than this loop:
 * <pre>
 *     for (Iterator i=list.iterator(); i.hasNext(); )
 *         i.next();
 * </pre>

 

    链表的实现只有LinkedList。


    这里我们主要讲解ArrayList和LinkedList,首先看ArrayList,它的类声明如下:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

 

他实现了RandomAccess支持随机访问,因为底层是数组嘛,知道下标访问速度是非常快的哈,并且实现了Serializable接口,代表这个类可以序列化以及反序列化,Cloneable则代表这个类可以被克隆,这个克隆啊又涉及到原型设计模式,原型涉及模式分为深克隆和浅克隆,有兴趣的朋友可以自己了解下本节不做讲解。

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer.
     */
    private transient Object[] elementData;

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

 

ArrayList中只有这2个成员变量,elementData则是用来存放具体数据的,size则用来标记数组实际大小,但是这里elementData为什么被transient修饰呢,被transient修饰则代表在序列化时会忽略elementData,难道elementData就不序列化了吗,并不是,而是ArrayList重写了writeObject方法,因为elementData每次满的时候都会扩充,会存在NULL没有使用的元素,所以重写了writeObject方法在序列化时只写入elementData的0到size实际使用的的数据。

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

 add添加元素时首先调用了ensureCapacity方法,这个方法会进行判断当前数组容量是否小于size+1,如果小于则扩充,扩充是调用的system.arraycopy的native方法来将数组copy到另一个扩充之后的数组中,然后把要添加的数据存放在elementData中。其余的方法和类都比较简单类似就不在说了。

    LinkedList底层使用Entry类来存放数据元素。

private static class Entry<E> {
    E element;
    Entry<E> next;
    Entry<E> previous;

    Entry(E element, Entry<E> next, Entry<E> previous) {
        this.element = element;
        this.next = next;
        this.previous = previous;
    }
}

 链表,就是手拉手,通过一个元素可以知道上一个元素和下一个元素,这个链表不了解的话可以先学习下数据结构这里就不在多说了,链表的遍历方式实现和数组是不一样的,

 

    private class ListItr implements ListIterator<E> {
	private Entry<E> lastReturned = header;
	private Entry<E> next;
	private int nextIndex;
	private int expectedModCount = modCount;

	ListItr(int index) {
	    if (index < 0 || index > size)
		throw new IndexOutOfBoundsException("Index: "+index+
						    ", Size: "+size);
	    if (index < (size >> 1)) {
		next = header.next;
		for (nextIndex=0; nextIndex<index; nextIndex++)
		    next = next.next;
	    } else {
		next = header;
		for (nextIndex=size; nextIndex>index; nextIndex--)
		    next = next.previous;
	    }
	}

	public boolean hasNext() {
	    return nextIndex != size;
	}

	public E next() {
	    checkForComodification();
	    if (nextIndex == size)
		throw new NoSuchElementException();

	    lastReturned = next;
	    next = next.next;
	    nextIndex++;
	    return lastReturned.element;
	}

 构造方法中初始化了next的值,if(int < (size >> 1))这里介绍下>>和>>>符号,>>代表向右移位,例如3>>1则代表二进制0011向右移动1位则是0001最终结果就是1,8>>>3代表8除以2的3次方最终结果则是1。

这里的if(int < (size >> 1))主要是为了判断这个元素时在前半段还是在后半段size >> 1相当于size/2,主要是为了更快的定位链表中第index元素的位置,不用从头遍历,这就是迭代器设计模式的好处,隐藏了内部实现的细节,对不同的数据结构提供了统一的迭代接口,就到这吧!

  • 大小: 15.4 KB
  • 大小: 6.3 KB
分享到:
评论

相关推荐

    java8源码-csn-list:ArrayList、LinkedList、Vector、Stack源码分析

    List相关实现类的源码解析(JDK1.8) 2018.9.22- List的架构图 ArrayList 继承关系: ArrayList -&gt; AbstractList 实现 List接口 ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态...

    Java软件开发实战 Java基础与案例开发详解 11-4 List接口实现类 共15页.pdf

    这部分内容主要聚焦于第11章的“Java集合框架和泛型机制”,特别关注List接口及其几种实现类,包括`ArrayList`、`LinkedList`、`Vector`以及`Stack`。 ### 11-4 List接口实现类 #### 11.4.1 实现类ArrayList - **...

    Java中的Map&List;

    List接口的实现类有多种,包括ArrayList、Vector、LinkedList、Stack等。 ArrayList类 ArrayList类是List接口的实现类,使用动态数组来存储对象。ArrayList类提供了多种方法来添加、删除、遍历集合中的对象。例如...

    map,list,set,stack,queue,vector等区别和特点1

    Stack是一个特殊的List,它是Vector的子类,实现了后进先出(LIFO)的数据结构,常用于模拟堆栈操作,如压栈、弹栈、查看栈顶元素等。Stack提供了push、pop、peek、empty和search等方法。 Queue接口代表先进先出...

    java常用集合类总结

    在线程安全的集合类中,Vector、Stack、Hashtable和Enumeration等类都是线程安全的,但性能较低,重量级的。这些类都是JDK1.1中引入的旧式集合类,现在已经被新的集合类所取代。 Java集合类提供了多种方式来存储和...

    JAVA容器效率深度分析List

    本文将深入分析Java中的List接口及其常见的实现类,如ArrayList、LinkedList和Vector,探讨它们的效率差异和适用场景。 首先,List是Java集合框架中的一个重要接口,它扩展了Collection接口,并规定了元素的有序性...

    javase集合 温故而知新.doc

    List接口的实现类有ArrayList、LinkedList、Vector等。ArrayList是使用数组实现的List,查找速度快,但删除添加元素慢。LinkedList是使用链表实现的List,查找速度慢,但删除添加元素速度快。Vector是ArrayList的...

    _Java-集合容器-2.List及其实现类.ppt

    List接口有多个实现类,包括ArrayList、LinkedList、Vector和Stack。 1. ArrayList实现类: ArrayList是List接口的一个常见实现,其内部基于动态数组实现。它提供了快速的随机访问,因为数组索引可以直接定位元素。...

    Java容器类的深入理解

    本文主要关注的是Java中的两种主要容器类型:Collection和Map,以及它们的一些具体实现,如List接口下的ArrayList、LinkedList和Vector,以及Map接口下的HashMap和Hashtable。 首先,我们来看List接口。List是有序...

    Java数据结构实现之Stack.zip

    - **LinkedList类与List接口**:LinkedList类实现了List接口,可以通过`addFirst()`和`removeFirst()`方法实现栈操作。但相比于ArrayDeque,LinkedList在进行栈操作时效率较低。 ```java LinkedList&lt;Integer&gt; ...

    java的list取之方法

    在Java中,`List`接口是`Collection`框架的一个重要组成部分,它继承自`Collection`接口。`List`是一种有序集合,允许包含重复元素。`List`的主要特点是可以通过索引访问元素,同时也支持插入、删除等操作。 ### ...

    List,set,Map 的用法和区别

    实现 List 接口的常用类有 LinkedList、ArrayList、Vector 和 Stack。LinkedList 类实现了 List 接口,允许 null 元素。此外 LinkedList 提供了额外的 get、remove、insert 方法在 LinkedList 的首部或尾部。这些...

    大公司最喜欢问的Java集合类面试题.docx

    List接口的实现类有LinkedList、ArrayList、Vector和Stack等。 LinkedList类是List接口的实现类,允许null元素。LinkedList提供了额外的get、remove、insert方法在LinkedList的首部或尾部。这些操作使LinkedList...

    java内置的数据结构.pdf

    Java中的List接口的实现包括ArrayList和LinkedList等。3. 集合(Set):集合是一种不允许重复元素的无序集合。Java中的Set接口的实现包括HashSet和TreeSet等。4. 映射(Map):映射是一种将键值对映射在一起的集合。...

    Java集合类详解总结

    Java集合框架主要包括`Collection`、`Set`、`List`、`Queue`、`Deque`、`Map`等接口和它们的具体实现类如`ArrayList`、`LinkedList`、`Vector`、`Stack`、`HashSet`、`HashMap`等。下面将对这些核心概念和类进行深入...

    区别和联系-list-map-set-vector

    List 提供了多种实现类,包括 `LinkedList`、`ArrayList`、`Vector` 和 `Stack`。 - **ArrayList**: 这是 List 最常用的实现之一。它基于动态数组实现,提供随机访问元素的功能。因此,添加或删除中间的元素效率较...

    子接口及其实现类PPT实用.pptx

    `List`接口的实现类有`ArrayList`和`LinkedList`: - `ArrayList`类:它基于可变大小的数组实现,允许存储包括`null`在内的所有元素。`ArrayList`提供了快速随机访问,但在插入和删除元素时可能不如`LinkedList`...

    Java 基础核心总结 +经典算法大全.rar

    ArrayList Vector LinkedList 类Stack HashSet TreeSet LinkedHashSet 类 PriorityQueue HashMap TreeMap 类 LinkedHashMap 类 Hashtable 类IdentityHashMap 类WeakHashMap 类 Collections 类集合实现类特征图 泛形 ...

    Java语言的Util类详细介绍

    实现List接口的常用类有LinkedList、ArrayList、Vector和Stack。LinkedList类实现了List接口,允许null元素。此外LinkedList提供额外的get、remove、insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被...

Global site tag (gtag.js) - Google Analytics