[置顶] Array ArrayList LinkList的区别剖析
这是一个面试中我们经常被问到的问题
Array、ArrayList、LinkList之间的区别:Array、ArrayList、LinkList均属于泛型的范畴,都用来存放元素,主要区别是Array是一个固定大小的容器,底层采用的是线性连续空间来存放元素,ArrayList同样也是一个容器,但是其大小不固定,底层采用的也是线性连续空间来存放元素,当线性连续空间不足以存放元素时,又重新申请一片更大的空间(大约是原空间的2倍),将原有的内容移过去,因此从这里可以看出,Array要比ArrayList的效率高,因为不需要重新申请空间,LinkList也是一个容器,但底层采用的是链表,因此不存在扩容问题,除非整个内存空间都不足了,由于采用的是链表,因此查找效率也比较低,但删除效率比较高。
Array测试源代码(其实这个压根没必要测试,大家都用过J):
//来个复杂点的吧
String [][]array=new String[5][];
//再加个for循环,每个小数组又是一个小数组
for(int i=0;i<5;i++){
array[i]=new String[i+1];
}
//从上面的代码中,可以看出的是数组的大小一旦确定,其内存空间的布局也就
//确定了,大小也就确定了
上面的代码,太简单了,每个Java书上都有,没有的,扔了它吧
ArrayList的测试代码:
//声明一个数组对象,采用的是ArrayList,从这里可以看出的是,ArrayList里可以存放任意
//类型,这也就是泛型
ArrayList<String> array=new ArrayList<String>();
//在这个数组对象里面存放元素
array.add("test1");
array.add("test2");
//将值打印出来
for(int i=0;i<array.size();i++)
System.out.println(array.get(i));
上面的代码,同样也是很简单的,不做分析,要分析的就是ArrayList与Array的不同,则要深入ArrayList的源代码
ArrayList核心源代码:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L; /**
从这里,可以看出的是,ArrayList里面是通过数组来存放元素的,数组名叫elementData,类型是Object
*/
private transient Object[] elementData; /**
* 数组的尺寸,上面有个关键字transient,有些人没见过,是用在Java的序列化时.
*
* @serial
*/
private int size; /**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
*下面这个是构造函数,从这里可以看出,如果声明时给构造函数传递了一个初始大小,则使用这个大小来开僻空间
* is negative
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
} /**
* 如果使用默认构造函数,则默认情况下会开僻一个10B的大小空间
*/
public ArrayList() {
this(10);
}
从上面的代码中,可以看出的是ArrayList的内层空间布局也是采用数组来实现的,因此与数组没什么区别,下面就看看其有区别的地方
不同之处的源代码:
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
上面这个函数是ArrayList中一个泛型向集合增加的方法,在这个方法中为了向集合中增加一个元素,必须要确定的是集合中有足够的空间,因此这个函数的关键是函数
ensureCapacity(size+1),再看看其源代码
public void ensureCapacity(int minCapacity) {
modCount++;
//获取当前容器的大小
int oldCapacity = elementData.length;
//如果填加一个元素后,新容器的大小minCapacity大于oldCapacity,则表示容器已
//无法存放元素了,执行下面的逻辑
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
//重新设定容器的大小,新容器的大小,为原来容器的150%倍+1
int newCapacity = (oldCapacity * 3)/2 + 1;
//容器增大后,如果还不够存放的话,就执行下面的逻辑
if (newCapacity < minCapacity)
//将容器的大小直接设为minCapacity
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
//这里会重新开僻空间,并将原来的元素copy进去
elementData = Arrays.copyOf(elementData, newCapacity);
}
上面我已经注释的很详细了,与Array的区别也是显而易见的,在容器容量不足时,会自动扩容
LinkList的测试源代码
//声明一个数组对象,采用的是LinkedList,从这里可以看出的是,LinkedList里可以存放任意
//类型,这也就是泛型
LinkedList<String> array=new LinkedList<String>();
//在这个数组对象里面存放元素
array.add("test1");
array.add("test2");
//将值打印出来
for(int i=0;i<array.size();i++)
System.out.println(array.get(i));
上面的代码与ArrayList没什么区别,是的,真正有区别的是在其实现上,看看LinkList实现的核心源代码吧:)
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{ //与ArrayList不同吧,不是用数组吧,有header,是不是想起链表了,是的,这里就是用链表
private transient Entry<E> header = new Entry<E>(null, null, null);
private transient int size = 0; /**
* 这个就是构造函数啦(默认的)指针均指向了header,看来还是个双向循环链表。.
*/
public LinkedList() {
header.next = header.previous = header;
}
从上面的代码中,可以看到的是里面真的是用链表实现的,你可以再看看其他的代码,只要理解C/C++里的链表,很容易理解的:)
[置顶] Array ArrayList LinkList的区别剖析的更多相关文章
- [置顶] String StringBuffer StringBuilder的区别剖析
这是一道很常见的面试题目,至少我遇到过String/StringBuffer/StringBuilder的区别:String是不可变的对象(final)类型,每一次对String对象的更改均是生成一个 ...
- [置顶] Vector ArrayList区别剖析
Java中Vector与ArrayList的区别?这是一个很常见的面试题目:) Vector与ArrayList其实是非常相似的,不信,你可以看看源码,如果说真的有什么区别的话,大概有以下三点: 1: ...
- [置顶]
strcpy()与strncpy()的区别
头文件:#include <string.h> strcpy() 函数用来复制字符串,其原型为: char *strcpy(char *dest, const char *src); [参 ...
- [置顶] strcpy和memcpy的区别
strcpy和memcpy都是标准C库函数,它们有下面的特点. strcpy提供了字符串的复制.即strcpy只用于字符串复制,并且它不仅复制字符串内容,还会复制字符串的结束符. 已知strcpy函数 ...
- [置顶]
TIM_GetCounter与TIM_GetCapture1的区别
/** * @brief Gets the TIMx Input Capture 1 value. * @param TIMx: where x can be 1 to 17 except 6 and ...
- c#中Array,ArrayList 与List<T>的区别、共性与转换
本文内容来自我写的开源电子书<WoW C#>,现在正在编写中,可以去WOW-Csharp/学习路径总结.md at master · sogeisetsu/WOW-Csharp (gith ...
- [置顶] Android开发笔记(成长轨迹)
分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...
- 自定义置顶TOP按钮
简述一下,分为三个步骤: 1. 添加Html代码 2. 调整Css样式 3. 添加Jquery代码 具体代码如下: <style type="text/css"> #G ...
- Android的SwipeToDismiss第三方开源框架模拟QQ对话列表侧滑删除,置顶,将头像图片圆形化处理。
<Android SwipeToDismiss:左右滑动删除ListView条目Item> Android的SwipeToDismiss是github上一个第三方开源框架(github ...
随机推荐
- 我也来玩玩WinForm~BeginInvoke让用户体验更好!
前言 先说明一下,本人不太做winform的项目,工作10年以来,一直奋斗在webform的舞台上,今天有机会也接触了一下winform,下面对工作中用到的BeginInvoke方法作一下说明,和大家 ...
- 在win10 64位下编译,提示[C++ Error] E2075 Incorrect project override option: (x86)\borland\cbuilder6\lib\vcl60.csm
options->compiler 右边有个file name 改下就好了从$(BCB)\lib\vcl60.csm 改为c:\PROGRA~1\borland\CBUILD~1\lib\vc ...
- 谈memcache和memcached的区别
用了段时间的memcache和memcached总结下认识,看很多人在用cache的时候,刚刚都没有搞清楚memcache 和 memcached的区别,还有就是使用的时候基本都是 get/set ...
- QSslError 类
QSslError Class Header: #include <QSslError> qmake: QT += network Since: Qt 4.3 注意:这个类中的所有函数都是 ...
- 关于 Log4Net
Log4Net是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件.数据库.EventLog等),日志就是程序的黑匣子,可以通过日志查看系统的运行过程,从而发现系统的问题.日志的作用:将运 ...
- Junit4拓展工具JCategory与Testng的Group功能比较
前言 笔者前段时间分享过一遍文章,关于如何通过引入新注解来扩展Junit4,以解决Process上的问题: JUnit扩展:引入新注解Annotation 最近在跟外面的同事聊的时候,得知Testng ...
- hg vs git :这个世界除了svn还有别的
最近想用版本控制软件来保存汉化文件,但又觉得SVN太麻烦,于是想到了最近较为流行的分布式版本控制工具.而Git和Mercurial(意思为水银的,于是经常缩写为Hg)自然是其中最为流行的工具.大名鼎鼎 ...
- 这篇blog只是为了发一张图链到UOJ的博客去..
UOJ卖萌表情,萌萌哒VFK如图.
- Keil编译后的各文件介绍
编译生成的文件: .plg:编译器编译结果 .hex和.bin:可执行文件 .map和.lst:链接文件 .obj:目标文件 .crf..lnp..d和.axf:调试文件 .opt:保存工程配置信息 ...
- 解决VS2005 VS2008 vs2010断点无效-源代码与原始版本不同
网上说的方法:(额~但是我就是不能用.但是也贴出来) 方法1.直接把整个文件格式化了一次,断点就可以用了Ctrl + A全选菜单:编辑-〉高级-〉设置选定内容的格式 (Ctrl+K, Ctrl+F)通 ...