【一】ArrayList

一ArrayList的内部结构

(1)ArrayList内部维护的是一个Object数组

(2)ArrayList数组扩容后数组的长度的公式:旧的数组长度+(旧数组长度>>1);

(3)ArrayList的subList()方法,并不会产生新的ArrayList对象,只是返回SubList对象,该对象持有ArrayList对象的引用,记录了截取的起始和结束的下标。

(4)ArrayList遍历方便,查找困难。相比较HashMap,更容易查找,遍历麻烦。

(5)ArrayList的内部是动态数组,动态数据就涉及到扩容问题。一旦需要扩容,就会产生新的数组,丢弃旧的数组。浪费效率。而且浪费内存。扩容后数组长度会更长,但数据不定存储那么多。

(6)trimToSize方法,可以将ArrayList中的数组大小和存储数据的个数一样,这样会进行一次新数组的创建,copy的过程。目的是为了减少内存不必要的浪费。

(7)

二ArrayList和数组的差别

这一节我们来讨论ArrayList与数组的差别,以及ArrayList的效率问题
  (1)ArrayList是Array的复杂版本
ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。
  (2)内部的Object类型的影响
         对于一般的引用类型来说,这部分的影响不是很大,但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的操作,频繁的操作可能会影响一部分效率。
但是恰恰对于大多数人,多数的应用都是使用值类型的数组。
消除这个影响是没有办法的,除非你不用它,否则就要承担一部分的效率损失,不过这部分的损失不会很大。
  (3)数组扩容
这是对ArrayList效率影响比较大的一个因素。
每当执行Add、AddRange、Insert、InsertRange等添加元素的方法,都会检查内部数组的容量是否不够了,如果是,它就会以当前容量的两倍来重新构建一个数组,将旧元素Copy到新数组中,然后丢弃旧数组,在这个临界点的扩容操作,应该来说是比较影响效率的。
     例1:比如,一个可能有200个元素的数据动态添加到一个以默认16个元素大小创建的ArrayList中,将会经过:
16*2*2*2*2 = 256
四次的扩容才会满足最终的要求,那么如果一开始就以:
ArrayList List = new ArrayList( 210 );
的方式创建ArrayList,不仅会减少4次数组创建和Copy的操作,还会减少内存使用。

例2:预计有30个元素而创建了一个ArrayList:
ArrayList List = new ArrayList(30);
在执行过程中,加入了31个元素,那么数组会扩充到60个元素的大小,而这时候不会有新的元素再增加进来,而且有没有调用TrimSize方法,那么就有1次扩容的操作,并且浪费了29个元素大小的空间。如果这时候,用:
ArrayList List = new ArrayList(40);
那么一切都解决了。
所以说,正确的预估可能的元素,并且在适当的时候调用TrimSize方法是提高ArrayList使用效率的重要途径。
   (4)频繁的调用IndexOf、Contains等方法(Sort、BinarySearch等方法经过优化,不在此列)引起的效率损失
首先,我们要明确一点,ArrayList是动态数组,它不包括通过Key或者Value快速访问的算法,所以实际上调用IndexOf、Contains等方法是执行的简单的循环来查找元素,所以频繁的调用此类方法并不比你自己写循环并且稍作优化来的快,如果有这方面的要求,建议使用Hashtable或SortedList等键值对的集合。

【二】LinkedList

(1)LinkedList内部维护的是一个基于Node对象的双向链表的数据结构。

 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;
}
}

(2)LinkedList提供了add(int index,Object object)和get(i)的方法。其底层都是基于二分法查找。将index和linkedLIst的size/2比较大小,决定在前半部分查找还是在后半部分查找。查找到插入数据或返回数据。

(3)LinkedList提供了一系列类似队列的方法。

public static void test02(){
LinkedList<String> linkedList=new LinkedList<String>();
linkedList.offer("a");//向链表末尾添加一个元素
linkedList.offerFirst("a");//向链表首端添加一个元素
linkedList.offerLast("a");//向链表末尾添加一个元素
linkedList.peek();//从链表首端取出一个元素。但不删除元素。
linkedList.peekFirst();//从链表首端取出一个元素。但不删除元素。
linkedList.peekLast();//从链表末尾取出一个元素。但不删除元素。
linkedList.poll();//从链表的首端取出一个元素。将当前元素从链表删除。
linkedList.pollFirst();//从链表的首端取出一个元素。将当前元素从链表删除。
linkedList.pollLast();//从链表的末尾取出一个元素。将当前元素从链表删除。
linkedList.pop();//从链表的首端取出一个元素。将当前元素从链表删除。
linkedList.push("a");//向链表的首端添加一个元素。
linkedList.subList(0,1);//内部也是形成一个包装类,持有原有链表的引用。 }

【三】ArrayList和LinkedList对比

ArrayList和LinkedList在性能上各有优缺点,都有各自所适用的地方,总的说来可以描述如下:
1.
对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一
项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。
2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
3.LinkedList不支持高效的随机元素访问。
4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间
可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

【java基础】java中ArrayList,LinkedList的更多相关文章

  1. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  2. java基础---->java中正则表达式二

    跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...

  3. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  4. Java基础学习中一些词语和语句的使用

    在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...

  5. Java基础-Java中的堆内存和离堆内存机制

    Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  6. Java基础-Java中的内存分配与回收机制

    Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.

  7. Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)

    Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...

  8. Java基础-Java中的并法库之线程池技术

    Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.

  9. Java基础__Java中自定义集合类

    Java基础__Java中集合类 传送门 自定义MyArrayList集合实现:增加数据.取数据.查看集合中数据个数方法 package com.Gary; public class MyArrayL ...

  10. Java基础(中)

    面向对象基础 面向对象和面向过程的区别 两者的主要区别在于解决问题的方式不同: 面向过程把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题. 面向对象会先抽象出对象,然后用对象执行方法的方式 ...

随机推荐

  1. Selenium入门练习(一)

    自主学习---上海野生动物园之登录.订票.退票 Create了一个TestNG可以查看执行结果: package FristTestNG; import java.sql.Driver; import ...

  2. zoj4028 LIS,差分约束

    题意:给你以i为结尾的最长上升子序列的值,和每个值的区间范围求可行的a[i] 题解:差分约束,首先满足l[i]<=a[i]<=r[i],可以建一个虚拟节点n+1,那么有a[n+1]-a[i ...

  3. SVN更新操作提示需要清理操作,清理操作提示乱码,更新SVN失败

    1.下载sqlite3.exe,下载方式如下: 1):sqlite网址:https://www.sqlite.org/download.html (根据操作系统自行下载) 2.下载的文件解压后将sql ...

  4. IOS-源代码管理工具(SVN)

    一.使用环境 要想利用SVN管理源代码,必须得有2套环境 服务器 用于存储客户端上传的源代码 可以在Windows上安装Visual SVN Server 大部分情况下,公司的开发人员不必亲自搭建SV ...

  5. Day11 - Python操作memcache、redis缓存、rabbitMQ队列

    本周课前必备: 1. Memcached 2. Python操作Memcached模块: https://pypi.python.org/pypi/python-memcached 3. Redis ...

  6. day5-import机制详述

    一.概述 但凡稍微复杂一些的python程序,都不可避免地需要import一些内置模块或外部模块,当然也有可能import进来一个package,java语言中也经常见到各种import打头,可见其用 ...

  7. Maven 环境搭建及相应的配置

    在一般的Java Web项目开发中,特别是基于Struts + hibernate + spring的框架的时候,会有很多的jar包,一般都会在项目文件中有一个lib文件夹,下面放所有相关的jar包. ...

  8. 021——VUE中变异方法 push/unshift pop/shift

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Prism 4 文档 ---第10章 Silverlight和WPF之间共享代码

        本主题帮助你理解来自Prism的多目标和它的优缺点.多目标的代码针对两个不同的平台有大致相同的代码库.这允许同时保持代码尽可能多一样能够产生针对两种不同技术的二进制文件.在这种情况下,本节介绍 ...

  10. hdu 5826 physics (物理数学,积分)

    physics Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...