(转载请标明出处)

1、ArrayLis t的实现

2、LinkedLis t的实现

3、ArrayList 和 LinkedList 的区别

ArrayList 的实现:

 1、MyArrayList将保持基础数组,数组的容量。以及存储在MyArrayList中的当前项数。 
  2、MyArrayList将提供一种机制以改变基础数组的容量。通过或者一个新数组,将老数组拷贝到新数组中改变数组的容量,允许虚拟机回收老数组。 
  3、MyArrayList将提供get和set的实现。 
  4、MyArrayList将提供基本的例程(Routine,系统对外提供的功能接口的集合),如size,isEmpty和clear,他们是典型的单行程序;还提供remove,以及两种不同版本的add。如果数组的大小和容量相同,那么这两个add例程将增加容量 。

  5、MyArrayList将提供一个实现Iterator接口的类。这个类将存储迭代序列中的下一项的下标,并提供next,hasNext和和remove等方法的实现。MyArrayList的迭代器方法直接返回实现Iterator接口的该类的新构造的实例。

public class MyArrayList<T> implements Iterator<T> {

    private static final int DEFAULT_CAPACITY = 10;

    private int theSize;
private T[] theItems; public MyArrayList() {
doClear();
} public void clear(){
doClear();
} private void doClear(){
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);
} public int size(){
return theSize;
} public void ensureCapacity(int newCapacity){
if(newCapacity < theSize){
return;
} T[] old = theItems;
theItems = (T[]) new Object[newCapacity];
for(int i = 0; i < size(); i++){
theItems[i] = old[i];
}
} public boolean add(T x){
add(size(),x);
return true;
} public void add(int idx, T x){
if(theItems.length == size()){
ensureCapacity(size() * 2 + 1);
}
for(int i = theSize; i > idx; i--){
theItems[i] = theItems[i-1];
theItems[idx] = x;
} theSize++;
} public T remove(int idx){
T removeItem = theItems[idx];
for(int i = idx; i < size() - 1; i++){
theItems[i] = theItems[i + 1];
}
theSize--;
return removeItem;
} public java.util.Iterator<T> iterator(){
return new ArrayListIterator<T>(this);
} private static class ArrayListIterator<T> implements Iterator<T>{ private int current = 0;
private MyArrayList<T> theList; public ArrayListIterator(MyArrayList<T> list) {
theList = list;
} @Override
public boolean hasNext() {
return current<theList.size();
} @Override
public T next() {
return theList.theItems[current++];
} }
...
}

LinkedList 的实现:

  1、MyLinkedList 类本身,包含到两端的链,表的大下以及一些方法。 
  2.、Node类,他可能是一个私有的嵌套类。一个节点包含数据以及到前一个节点的链和到下一个节点的链,还有一些适当的构造方法。 
  3.、LinkedListIterator 类,该类抽象了位置的概念,是一个私有类,并实现接口Iterator。它提供了方法next,hasNext,remove的实现。

public class MyLinkedList<T> implements Iterator<T> {

    private int theSize;
private int modCount = 0;
private Node<T> beginMarker;
private Node<T> endMarker; private static class Node<T>{ public T data;
public Node<T> prev;
public Node<T> next; public Node(T d, Node<T> p,Node<T> n){
data = d;
prev = p;
next = n;
}
} public MyLinkedList(){
doClear();
} public void clear(){
doClear();
} private void doClear() { beginMarker = new Node<T>(null,null,null);
endMarker = new Node<T>(null,beginMarker,null);
beginMarker.next = endMarker; theSize = 0;
modCount++;
} public int size(){
return theSize;
} public boolean isEmpty(){
return size() == 0;
} public boolean add(T x){
add(size(),x);
return true;
} private Node<T> getNode(int idx){
return getNode(idx,0,size()-1);
} private Node<T> getNode(int idx, int lower, int upper ){
Node<T> p; if(idx < lower || idx > upper){
throw new IndexOutOfBoundsException();
} if(idx < size()/2 ){
p=beginMarker.next;
for(int i= 0; i < idx; i++){
p = p.next;
}
}else{
p=endMarker;
for(int i = size();i > idx; i--){
p = p.prev;
}
}
return p;
} public void add(int idx, T x){
addBefore(getNode(idx,0,size()),x);
} public T get(int idx){
return getNode(idx).data;
} public T set(int idx, T newVal){
Node<T> p = getNode(idx);
T oldVal = p.data;
p.data = newVal;
return oldVal;
} public T remove(int idx){
return remove(getNode(idx));
} private void addBefore(Node<T> p, T x){
Node<T> newNode = new Node<T>(x,p.prev,p);
newNode.prev.next = newNode;
p.prev = newNode;
theSize++;
modCount++;
} private T remove(Node<T> p){
p.next.prev = p.prev;
p.prev.next = p.next;
theSize--;
modCount++; return p.data;
} public java.util.Iterator<T> iterator(){
return new LinkedListIterator();
} private class LinkedListIterator implements Iterator<T>{ private Node<T> current = beginMarker.next;
private int expectedModCount = modCount;
private boolean okToRemove = false; @Override
public boolean hasNext() {
return current != endMarker;
} @Override
public T next() { if(modCount != expectedModCount){
throw new java.util.ConcurrentModificationException();
} if(!hasNext()){
throw new java.util.NoSuchElementException();
} T nextItem = current.data;
okToRemove = true;
return nextItem;
} public void remove(){
if(modCount != expectedModCount){
throw new java.util.ConcurrentModificationException();
}
if(!okToRemove){
throw new IllegalStateException();
} MyLinkedList.this.remove(current.prev);
expectedModCount++;
okToRemove = false;
}
}
  ...
}

  

ArrayList 和 LinkedList 的区别:

 结构上的区别:

   对于处理一列数据项,ArrayList 的内部实现是基于内部数组Object[],所以从概念上讲,它更像数组,但 LinkedList 的内部实现是基于一组连接的记录,所以,它更像一个链表结构;ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。

          

 性能上的区别:

   查询:

    二分查找法使用的随机访问(random access)策略,而LinkedList是不支持快速的随机访问的(访问链表中的某个元素时,就必须从链表的一端开始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止)。对一个LinkedList做随机访问所消耗的时间与这个表的大小是成比例的。而相应的,在ArrayList中进行随机访问所消耗的时间是固定的。

          

   增删:

    1、若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。

    2、若是批量插入或删除数据:

     ArrayList 是基于数组实现的,而数组是一块连续的内存空间,当在表的前面或中间插入或删除元素时,所有已经存在的元素都会后移,这就意味着数据移动和复制上的开销,当在表的后面插入或删除元素时,ArrayList和LinkedList数据量小时速度相差无几,但数据量较大时ArrayList的速度快。在末尾插入或删除数据,arraylist的速度比linkedlist的速度反而要快。:其实在前方插入时,ArrayList可以使用后方插入,最后再使用Collections.reverse()方法反转,速度比LinkedList快。

     LinkedList 插入或删除数据则只是简单的未这个元素分配一个记录,然后调整两个连接,在表的尾端插入数据与在任意位置插入数据是一样的,不会因为插入的位置靠前而导致插入的方法性能降低。

          

   遍历列表:最简便的ForEach循环并没有很好的性能表现,综合性能不如普通的迭代器,而是用for循环通过随机访问遍历列表时,ArrayList表项很好,但是LinkedList的表现却无法让人接受,甚至没有办法等待程序的结束。这是因为对LinkedList进行随机访问时,总会进行一次列表的遍历操作。性能非常差,应避免使用。

      

 性能开销:

  在LinkedList中有一个私有的内部类,

private static class Node<T>{

        public T data;
public Node<T> prev;
public Node<T> next; public Node(T d, Node<T> p,Node<T> n){
data = d;
prev = p;
next = n;
}
}

  每个Node对象 reference列表中的一个元素,同时还有在LinkedList中它的上一个元素和下一个元素。一个有1000个元素的LinkedList对象将 有1000个链接在一起的Node对象,每个对象都对应于列表中的一个元素。这样的话,在一个LinkedList结构中将有一个很大的空间开销,因为 它要存储这1000个Node对象的相关信息。

        

  ArrayList使用一个内置的数组来存储元素,这个数组的起始容量是10.当数组需要增长时,新的容量按 如下公式获得:新容量=(旧容量*3)/2+1,也就是说每一次容量大概会增长50%。这就意味着,如果你有一个包含大量元素的ArrayList对象, 那么最终将有很大的空间会被浪费掉,这个浪费是由ArrayList的工作方式本身造成的。如果没有足够的空间来存放新的元素,数组将不得不被重新进行分 配以便能够增加新的元素。对数组进行重新分配,将会导致性能急剧下降。如果我们知道一个ArrayList将会有多少个元素,我们可以通过构造方法来指定容量。我们还可以通过trimToSize方法在ArrayList分配完毕之后去掉浪费掉的空间。 

    

 总结:

  1、在ArrayList的 中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。

   2、ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间。

   3、LinkedList不 支持高效的随机元素访问。

   4、ArrayList的查询效率比较高,增删动作的效率比较差,适用于查询比较频繁,增删动作较少的元素管理的集合。

    LinkedList的查询效率低,但是增删效率很高。适用于增删动作的比较频繁,查询次数较少的元素管理集合。

ArrayList 和 LinkedList 的实现与区别的更多相关文章

  1. 集合中list、ArrayList、LinkedList、Vector的区别、Collection接口的共性方法以及数据结构的总结

    List (链表|线性表) 特点: 接口,可存放重复元素,元素存取是有序的,允许在指定位置插入元素,并通过索引来访问元素 1.创建一个用指定可视行数初始化的新滚动列表.默认情况下,不允许进行多项选择. ...

  2. java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析

    java面试中经常被问到list常用的类以及内部实现机制,平时开发也经常用到list集合类,因此做一个源码级别的分析和比较之间的差异. 首先看一下List接口的的继承关系: list接口继承Colle ...

  3. ArrayList和LinkedList 的联系和区别

    ArrayList和LinkedList 的联系和区别 1.联系: 都实现了List接口 有序 不唯一(可重复) 2.区别 ArrayList LinkedList

  4. java的List接口的实现类 ArrayList,LinkedList,Vector 的区别

    Java的List接口有3个实现类,分别是ArrayList.LinkedList.Vector,他们用于存放多个元素,维护元素的次序,而且允许元素重复. 3个具体实现类的区别如下: 1. Array ...

  5. 数组Array和列表集合ArrayList、LinkedList和Vector的区别

    一.ArrayList和Vector的区别 ArrayList与Vector主要从以下方面来说. 1.同步性: Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同 ...

  6. 描述一下ArrayList和LinkedList各自实现和区别

    ArrayList,LinkedList,Vestor这三个类都实现了java.util.List接口,但它们有各自不同的特性,主要如下: 一.同步性 ArrayList,LinkedList是不同步 ...

  7. java中ArrayList、LinkedList、Vector的区别

    ArrayList.LinkedList.Vector这三个类都实现了List接口. ArrayList是一个可以处理变长数组的类型,可以存放任意类型的对象.ArrayList的所有方法都是默认在单一 ...

  8. ArrayList和LinkedList的共同点和区别

    ArrayList和LinkedList的相同点和不同点 共同点:都是单列集合中List接口的实现类.存取有序,有索引,可重复 不同点: 1.底层实现不同: ArrayList底层实现是数组,Link ...

  9. ArrayList、LinkedList、Vector的区别

    Arraylist和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以插入数据慢,查找有下标, ...

随机推荐

  1. jeecg 3.7.1 新版功能,集群定时任务动态发布模块 使用规则

    jeecg 3.7.1  集群定时任务动态发布模块 使用规则   新版特性:    支持集群定时任务,支持分布式. 菜单路径: 系统监控-->定时任务 字段说明: 任务ID.任务说明:自定义即可 ...

  2. [REST] 1.REST的起源

    0. 世界上第一个网站 1990年12月20日,这一天对于现在的互联网来说意义非凡.欧洲核子研究组织(CREN)的科学家Tim Berners-Lee在一台NeXT电脑上启动了世界上的第一个网站(当然 ...

  3. css 禁止长按保存功能

    *{-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} 或者指定某个元 ...

  4. HDMI转EDP芯片NCS8803简介

    NCS8803 HDMI-to-eDP w/ Scaler Features --Embedded-DisplayPort (eDP) Output 1/2/4-lane eDP @ 1.62/2.7 ...

  5. sqlserver优化

    有些程序员在撰写数据库应用程序时,常专注于 OOP 及各种 framework 的使用,却忽略了基本的 SQL 语句及其「性能 (performance)优化」问题.版工曾听过台湾某半导体大厂的新进程 ...

  6. chrome开发工具指南(十一)

    检查资源 使用 Application 面板的 Frames 窗格可以按框架组织资源. 您也可以在 Sources 面板中停用 Group by folder 选项,按框架查看资源. 要按网域和文件夹 ...

  7. Tomcat session生成算法

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt396 修改TOMCAT 默认的生成SESSION ID的算法和字符长度非常简 ...

  8. javascript中用setAttribute给元素添加colspan属性无效

    先附上代码 var tr=document.createElement('TR'); var td=document.createElement('TD'); td.setAttribute('col ...

  9. 如何在sublime+chrome中调试php代码?

    1.搭建php本地运行环境具体点击如何使用phpstudy本地搭建多站点(每个站点对应不同的端口) 2.下载php_xdebug.dll, [5.3版以上的php下载地址]http://pecl.ph ...

  10. 【2017集美大学1412软工实践_助教博客】团队作业8——第二次项目冲刺(Beta阶段)

    题目 团队作业8: http://www.cnblogs.com/happyzm/p/6856179.html 团队作业8-1 beta冲刺计划 团队 新加入的成员,担当的角色,技术特点 下一阶段需要 ...