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 的实现与区别的更多相关文章
- 集合中list、ArrayList、LinkedList、Vector的区别、Collection接口的共性方法以及数据结构的总结
		
List (链表|线性表) 特点: 接口,可存放重复元素,元素存取是有序的,允许在指定位置插入元素,并通过索引来访问元素 1.创建一个用指定可视行数初始化的新滚动列表.默认情况下,不允许进行多项选择. ...
 - java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析
		
java面试中经常被问到list常用的类以及内部实现机制,平时开发也经常用到list集合类,因此做一个源码级别的分析和比较之间的差异. 首先看一下List接口的的继承关系: list接口继承Colle ...
 - ArrayList和LinkedList 的联系和区别
		
ArrayList和LinkedList 的联系和区别 1.联系: 都实现了List接口 有序 不唯一(可重复) 2.区别 ArrayList LinkedList
 - java的List接口的实现类 ArrayList,LinkedList,Vector 的区别
		
Java的List接口有3个实现类,分别是ArrayList.LinkedList.Vector,他们用于存放多个元素,维护元素的次序,而且允许元素重复. 3个具体实现类的区别如下: 1. Array ...
 - 数组Array和列表集合ArrayList、LinkedList和Vector的区别
		
一.ArrayList和Vector的区别 ArrayList与Vector主要从以下方面来说. 1.同步性: Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同 ...
 - 描述一下ArrayList和LinkedList各自实现和区别
		
ArrayList,LinkedList,Vestor这三个类都实现了java.util.List接口,但它们有各自不同的特性,主要如下: 一.同步性 ArrayList,LinkedList是不同步 ...
 - java中ArrayList、LinkedList、Vector的区别
		
ArrayList.LinkedList.Vector这三个类都实现了List接口. ArrayList是一个可以处理变长数组的类型,可以存放任意类型的对象.ArrayList的所有方法都是默认在单一 ...
 - ArrayList和LinkedList的共同点和区别
		
ArrayList和LinkedList的相同点和不同点 共同点:都是单列集合中List接口的实现类.存取有序,有索引,可重复 不同点: 1.底层实现不同: ArrayList底层实现是数组,Link ...
 - ArrayList、LinkedList、Vector的区别
		
Arraylist和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以插入数据慢,查找有下标, ...
 
随机推荐
- scrapy使用
			
我们都知道大名鼎鼎的爬虫框架scrapy,它是基于twisted框架基础上进行的封装,它是基于异步调用,所以爬取的速度会很快,下面简单介绍一下scrapy的组成. 首先我们先安装scrapy,如果是基 ...
 - Tomcat知识1
 - 关于package.json的理解
			
在我们打包项目的时候或者使用node的时候,常常会看到package.json这个文件,里面乱七八糟的一大堆json,开始的时候没注意,以为是使用node或者npm的时候自动创建的,后来自己写demo ...
 - node.js后台快速搭建在阿里云(二)(pm2和nginx篇)
			
前期准备 阿里云服务器 node.js pm2 express nginx linux(推荐教程:鸟哥的私房菜) 简介 嗯……我只是个前端而已 在第一部分说完了express篇. 后面继续项目的部署, ...
 - vs下开端口直接调试iis
			
有些时候我们接口调试不想发布然后挂到iis下面,因为这样子调试有点麻烦,不是不可以调试.当然我们就希望在vs下直接运行直接打断点调试! 只需要三步就可以实现: 1) 找到这个文件 2) 打开上面文 ...
 - 开源分享 Unity3d客户端与C#分布式服务端游戏框架
			
很久之前,在博客园写了一篇文章,<分布式网游server的一些想法语言和平台的选择>,当时就有了用C#做网游服务端的想法.写了个Unity3d客户端分布式服务端框架,最近发布了1.0版本, ...
 - 如何搭建Zookeeper集群
			
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的 ...
 - 【 DCOS 】织云 CMDB 管理引擎技术详解
			
欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者 : 李琦 , 腾讯高级工程师 , 就职于网络平台部.曾负责公司海量运营系统的规划设计,如 TMP.Sniper.GSLB.IDCSp ...
 - spring事务失效情况分析
			
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt113 <!--[if !supportLists]-->一.&l ...
 - python--对于装饰器的理解
			
1.首先,有个原来写好的函数,完成一定的功能,比如下面的,就打印一句话(某程序被调用).简单点,容易帮我们想清楚程序是怎么执行的. ''' 原函数 ''' def fun1(): print(&quo ...