`

集合框架 List篇(1)---ArrayList、LinkedList

 
阅读更多
List
-----------
1.ArrayList(jdk1.5以前版本中Vector)
2.LinkedList(jdk1.5以前版本中Stack)
3.CopyOnWriteArrayList

------------------------------

ArrayList是数组的实现形式(内部存储结构是一个数组):

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

  private transient Object[] elementData;//存储元素的数组

//ArrayList的构造方法

public ArrayList(int initialCapacity) {//initialCapacity表示要创建的数组的容量
         super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
        this.elementData = new Object[initialCapacity];//创建initialCapacity长度的数组
    }

    /**
     *默认的构造 容量为10

     */
    public ArrayList() {
       this(10);
    }

    /**
     * 通过传入集合变量的形式初始化创建list的数组

     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
           elementData = Arrays.copyOf(elementData, size, Object[].class);
     }
-----------------------------

//添加新的元素到数组末尾时,如果超过了当前容量,就要对数组进行扩容,扩充为原来大小的1.5倍,

//由于扩容牵涉到整个数组的copy,对性能影响较大,所以如果知道要存放容量的大小,尽量在创建ArrayList时指定

 public void ensureCapacity(int minCapacity) {
 modCount++;
 int oldCapacity = elementData.length;
 if (minCapacity > oldCapacity) {
     Object oldData[] = elementData;
     int newCapacity = (oldCapacity * 3)/2 + 1;
         if (newCapacity < minCapacity)
                   newCapacity = minCapacity;
            // minCapacity is usually close to size, so this is a win:
          elementData = Arrays.copyOf(elementData, newCapacity);
 }

}

-----------------------------------

//get方法实现很简单,就是指定到数组的index下标处,效率很高

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

 return (E) elementData[index];
}
------

添加元素后扩容情况的效果图:



//添加元素的方法,注意先调用ensureCapacity,保证有足够的容量(如果不足就扩容,上面有该方法介绍)

//由于add方法添加元素时,可能导致扩容操作,这也影响了其效率

public boolean add(E e) {
  ensureCapacity(size + 1);  

  elementData[size++] = e;
  return true;
}

-----

删除元素的效果图:



//删除元素的remove操作,牵涉到删除位置index后边元素的copy,所以ArrayList的remove操作效率不高

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

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

 int numMoved = size - index - 1;//删除位置后边的元素个数
   if (numMoved > 0)//把要删除位置index后边的元素重新copy到数组的index处及以后
     System.arraycopy(elementData, index+1, elementData, index,  numMoved);

   elementData[--size] = null; // 把最后一个位置的元素置空,便于垃圾回收

    return oldValue;
 }
------------------

ensureCapacity

说明:ArrayList就是一个数组实现,适用于,  查找操作较多,而修改操作(add和delete)较少的情况,由于实现较为简单,就不再过多介绍,如果想更详细了解其实现,可以查看其源码。

下面要介绍的LinkedList适用于:查找较少,修改较多的情况(这与LinkedList的链式结构是有关系的)。

-------------------------------

LinkedList是链表结构的实现形式(内部存储结构是一个链表形式):



存储结构图示

LinkedList的类结构

public class LinkedList <E>    extends AbstractSequentialList<E>    implements List<E>, Deque<E>, Cloneable, java.io.Serializable


LinkedList的成员变量

private transient Entry<E> header = new Entry<E>(null, null, null);//链表的头结点
 private transient int size = 0;//链表中元素的个数

LinkedList的构造方法

   
/**
     * 构造一个空链表
     */
    public LinkedList() {
        header.next = header.previous = header;
    }

    /**
     * 通过传入一个集合初始化新链表

     */
    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

addAll方法

 public boolean addAll(int index, Collection<? extends E> c) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew==0)
            return false;
        modCount++;

        Entry<E> successor = (index==size ? header : entry(index));//后继结点,如果index==size时,后继结点指向header头结点
        Entry<E> predecessor = successor.previous;//前驱结点
        for (int i=0; i<numNew; i++) {//把集合元素连成一个双向子链表
            Entry<E> e = new Entry<E>((E)a[i], successor, predecessor);
            predecessor.next = e;
            predecessor = e;
         }
         successor.previous = predecessor;//“原始的后继结点"的前驱指向新子链表的最后一个结点

         size += numNew;//更新size大小
        return true;
    }

LinkedList的节点存储结构
private static class Entry<E> {//以内部类的形式定义Entry
 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;
 }
}

------------------------

LinkedList的get操作

//get操作,调用entry(index)方法,获得位置index位置的Entry对象
public E get(int index) {
    return entry(index).element;
}
//通过index得到指定位置的Entry结点
private Entry<E> entry(int index) {
   if (index < 0 || index >= size)
     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
   Entry<E> e = header;
   if (index < (size >> 1)) {//优化了查找操作,如果index<size/2就从头结点向后遍历
       for (int i = 0; i <= index; i++)
          e = e.next;
   } else {//否则,向前遍历
       for (int i = size; i > index; i--)
          e = e.previous;
   }
   return e;
}

LinkedList的add操作

添加新元素到链表的末端,图示如下:


//add操作,把元素添加到链表的未段
public boolean add(E e) {
   addBefore(e, header);
   return true;
}


//把新元素e添加到entry的前面,当entry为header头结点时,相当于添加到链表的末端,如上图所示
private Entry<E> addBefore(E e, Entry<E> entry) {
   Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);//以entry作为后继,以entry的前驱作为前驱
   newEntry.previous.next = newEntry;//更新引用
   newEntry.next.previous = newEntry;
   size++;//元素个数 加1
   modCount++;//修改次数 加1

  return newEntry;
}

----------------------------

LinkedList的delete操作

删除元素E3,图示如下:


//remove操作,先调用entry(index)方法(上面有介绍)获得Entry对象,然后调用remove(entry)
public E remove(int index) {
    return remove(entry(index));
}
//执行删除操作
private E remove(Entry<E> e) {
   if (e == header)
      throw new NoSuchElementException();

   E result = e.element;
   e.previous.next = e.next;//改变e前驱结点的next引用
   e.next.previous = e.previous;//改变e后继结点的previous引用
   e.next = e.previous = null;//把e置空,便于GC回收
   e.element = null;

   size--;//元素个数 减1
   modCount++;//修改次数 加1

  return result;
}
----------

另外,由于LinkedList实现了双向队列Deque接口,所以也具有队列的相关操作,可以当做一个队列使用。
  • 大小: 22.2 KB
  • 大小: 31.3 KB
  • 大小: 30.3 KB
  • 大小: 11.6 KB
  • 大小: 12.3 KB
分享到:
评论

相关推荐

    arraylist-linkedlist-test.zip

    ArrayList和LinkedList是Java集合框架中两种重要的动态数组实现,它们都是List接口的实现类,但它们在存储和操作数据方面有着显著的区别。本文件"arraylist-linkedlist-test.zip"主要探讨了在执行添加和删除元素操作...

    【IT十八掌徐培成】Java基础第10天-03.List-集合框架-ArrayList.zip

    本课程“【IT十八掌徐培成】Java基础第10天-03.List-集合框架-ArrayList”深入讲解了Java中的ArrayList类,这是集合框架中的一个重要组成部分,特别适用于对元素有序且可变大小的需求。 ArrayList是Java.util包下的...

    集合框架介绍----各种接口的方法

    Java集合框架是Java编程语言中一个非常重要的组成部分,它提供了一组用来操作和管理对象的接口和类。这个框架使得开发者能够以统一的方式处理各种数据结构,如列表、集合并和映射。以下是对集合框架及其接口的详细...

    java基础--list(ArrayList、LinkedList、匿名类).docx

    在Java编程中,List接口是集合框架的重要组成部分,提供了有序存储元素的功能。ArrayList和LinkedList是List接口的两种主要实现,它们各有优缺点,适用于不同的场景。此外,匿名类的概念在Java中用于简化代码结构,...

    比较ArrayList、LinkedList、Vector1

    List接口是Java集合框架中的重要组成部分,它是一个有序的集合,允许重复元素,并且保持插入顺序。List接口的实现类主要有ArrayList、LinkedList和Vector。 2. **ArrayList** - **实现原理**:ArrayList基于动态...

    java 集合(list-queue-set)学习

    首先,List接口是Java集合框架中用于存储有序元素的接口,它允许元素重复,并且可以通过索引来访问元素。ArrayList和LinkedList是List接口的两种常见实现。ArrayList基于动态数组,适合于频繁的随机访问,因为它的...

    精通java集合框架--List,Set..

    ### 精通Java集合框架——List, Set, Map #### 概述 Java集合框架是一种高度抽象且灵活的数据组织工具,它通过一系列接口来定义不同类型的数据容器,并提供了丰富的操作这些容器的方法。本文将深入探讨Java集合...

    java提高篇(二一)-----ArrayList.pdf

    在了解和使用ArrayList之前,应当熟悉Java集合框架的基础知识,以及数组的动态增长机制。 知识点一:ArrayList的定义和基本特性 ArrayList是一个可以动态增长和缩减的数组实现。它允许所有的元素,包括null。...

    学士后Java集合框架和泛型课后习题答案

    在Java中,集合框架主要包括接口(如List、Set、Queue)和实现这些接口的类(如ArrayList、HashSet、LinkedList等)。这个框架允许我们高效地处理各种数据结构,而无需从头开始编写代码。泛型则是Java 5引入的一项...

    Map+List+ArrayList+LinkedList Java源码

    Java编程语言中的`Map`, `List`, `ArrayList` 和 `LinkedList` 是四个核心的数据结构,它们在实际开发中被广泛使用。了解它们的源码对于深入理解Java集合框架的内部工作原理至关重要,尤其是对初学者而言,这有助于...

    Java 集合框架(1-9)-Collection 类关系图.pdf

    Java集合框架是Java编程语言中的一个核心组成部分,它提供了一套通用的数据结构和容器,用于存储和管理对象。集合框架自JDK 1.2引入以来,极大地提升了开发效率,优化了程序性能,并增强了不同API之间的互操作性。在...

    Java集合框架pdf--培训中心资料

    ### Java集合框架知识点详解 #### 一、Java集合框架概览 Java集合框架是一组用于存储和操作数据的API,提供了多种数据结构和算法来帮助开发者高效地管理和处理数据。集合框架主要包括`Collection`和`Map`两个顶层...

    集合ArrayList测试集合ArrayList测试集合ArrayList测试

    Java提供两种主要类型的集合框架:接口(如`List`、`Set`和`Queue`)和实现这些接口的类(如`ArrayList`、`HashSet`和`LinkedList`)。`ArrayList`作为`List`接口的一个实现,其特点是元素按索引顺序存储,索引是从0...

    java集合 collection-list-LinkedList详解

    在Java集合框架中,`List`接口是`Collection`接口的一个子接口,它代表了有序的元素列表,其中元素可以重复,并且可以通过索引来访问。`LinkedList`类是实现`List`接口的一个具体类,它提供了链表结构的数据存储方式...

    Java集合类List-Set-Map的区别和联系.doc

    Java集合框架是编程中不可或缺的一部分,它提供了多种数据结构,如List、Set和Map,用于存储和管理对象。下面我们将详细探讨这些集合类的区别、联系以及何时选择它们。 首先,数组(Array)是最基础的数据结构,它...

    java集合框架图

    在Java集合框架中,主要有六种核心接口:`Collection`, `Set`, `List`, `Queue`, `Deque`, 和 `Map`。此外,还有五个抽象类以及多个实现类,它们共同构成了Java集合框架的基础。 #### 二、核心接口介绍 1. **`...

    集合框架学习笔记

    这篇学习笔记将深入探讨Java集合框架的基础概念、主要类库以及常见应用场景。 首先,Java集合框架分为两种基本类型:List(列表)和Set(集)。List接口代表有序的集合,允许重复元素,如ArrayList和LinkedList;而...

    08-《集合框架-1》.rar

    本教程“08-《集合框架-1》”旨在深入讲解Java集合框架的基础概念和核心类,帮助学习者掌握如何在实际项目中有效地利用这些工具。 Java集合框架主要分为两大接口:List和Set。List接口代表有序的、可重复的元素集合...

Global site tag (gtag.js) - Google Analytics