array和ArrayList的区别
array
和ArrayList
两者都是 Java 中重要的数据结构,在Java程序中运用非常频繁,尽管ArrayList
内部是由一个array
实现的,array
和ArrayList
之间还是有很多的不同点。array
提供 O(1)的查找性能和连续的stroage block去存储数据。
ArrayList
是Java集合框架类的一员,可以称它为一个动态数组。array
是静态的,所以一个数组一旦创建就无法更改他的长度。如果需要一个数组可以重新定义他的大小,应该使用ArrayList,
这是array
和ArrayList
的基本的不同。
那么让我们从下面几个point来比较一下array
和ArrayList
1) Implementation 实现
array
是本地的程序设计组件或者数据结构(primitive),但是ArrayList
是一个来自Java集合类的类,这个ArrayList类源于一个接口List。 实际上ArrayList
在Java上,它的内部是由一个array
实现的。既然ArrayList
是一个类,那么它就持有了所有类的属性。例如,可以创建对象,可以调用方法,但是array
并不提供任何方法,它仅仅暴露了一个常量的长度来表示当前数组的长度(length)。
2) Performance 性能
既然ArrayList
是基于array,
所以可能会认为它提供和array
一样的性能。这个假设在一定程度上是成立的,但是在一些额外功能上ArrayList
的性能还是和array
存在一定差别,主要是内存的使用和CPU 耗时。在索引上,ArrayList
和array
都能提供O(1)的时间复杂度,但是在添加item的时候如果触发resize,ArrayList
可能会是O(logN)的时间复杂度,因为它包含了创建一个新的array
和将老的array
的数据拷贝到新的array
里。在存储相同数量的对象时,ArrayList
所需要的内存也是比array
大的。例如一个int[] 的数组会比ArrayList
节省20个int 变量的大小,因为对象的基本数据会在ArrayList
和包装类上进行开销。
3) Type Safety 类型安全
ArrayList
是类型安全的,因为它支持泛型(Generics) 允许编译器检查ArrayList
里所包含的对象是否是正确的类型.然而,array
并不支持泛型.这代表在编译时期检查array
所保存对象的类型是不可能的,但是array
通过抛出ArrayStoreException
异常的方式来进行运行时的类型检查如果你存储了一个错误类型的对象,例如,存储一个String
到intarray
里
4) Flexibility 灵活性
灵活性是区分array
和ArrayList
最重要的一个东西,简单来说,ArrayList
比简单的array
要灵活的多,因为ArrayList
是动态的,它可以在需要的时候扩大自己的内存,这是一个array
不可能做到的.ArrayList
也允许你删除元素, 这在array
上也是不可能的.通过删除,我的意思并不是将null置于对应的index里,而是将所删除元素的后面所有元素的index都往前移动一位,这些都是ArrayList
自动为我们做的
5) Primitives 基本类型
如果你第一次开始使用Arraylist,你会发现,你不能保存基本类型到ArrayList
里,这是array
和ArrayList
一个关键的不同,因为array
既可以保存对象也可以保存基本类型.例如.int[]数组是合法的,但是一个int型的ArrayList
是不合法的. 如何解决这个问题呢? 假设你想存储int类型到ArrayList
里,你会怎么做呢? 是的,你可以用封装类,这就是封装类被引进java的原因之一.所以,从java5开始,这个区别越来越不明显了,因为通过自动封装你会发现ArrayList.add(21)
是非常合法并且运行正常.
6) Generics 泛型
ArrayList
和array
之间的另外一个重要的区别就是前者能够显示的支持泛型,后者不行.由于数组是协变性的,所以你可以在array
上使用泛型(Since an
arrayis of covariant type, you can use Generics with them
).这个表示编译器不可能检查array
的类型安全,但是可以校验类型安全.当你要写一个类型安全的类的时候如何解决这个问题呢?好吧,你可以用里展示的技术,通过申明一个类似于E[]的数组,然后后期进行类型转换.
7) Iteration 迭代
ArrayList
提供比array
更多的方式来迭代一个接一个的访问所有的元素.可以通过for,while等循环来遍历array
,但是你可以通过Iterator
和ListIterator
类来遍历ArrayList
.看这里来了解更多的遍历ArrayList
的方式.
8) Supported Operations 支持的操作
由于ArrayList
的内部是由一个array
支撑着,所以它暴露了能够在array
可能支持的操作,并且还提供了它动态的属性.它也支持添加操作,这是在array
上不可能的.你可以同时在array
和ArrayList
上存储元素,但是仅ArrayList
允许你删除元素.然而你可以通过模拟将null赋值到对应的index里来模拟删除.这个模拟不会像是删除,除非你同时将所删除元素对应的索引(index)移动到下一级
ArrayList
和array
头提供取元素的方法.例如ArrayList
用索引通过get()方法来获取一个元素, version[0]将会返回array
的第一个元素.ArrayList
也提供一个方法来清空和重用例如,clear()
和removeAll()
.array
并不提供那些方发,但是你可以通过循环这个数组来将null赋值到所有的元素里来模拟ArrayList
的removeAll()
9) Size() vs length 大小 vs 长度
array
仅仅提供一个length
属性来告诉你array
里有多少个插槽,例如可以存储多少个元素.它没有提供任何方法来告诉你哪些插槽是满的,哪些是空的.例如,当前元素的个数.但是ArrayList
提供一个size()
方法来告诉你当前时间点ArrayList
存储了多少个元素.size()
总是和length
不同的,它也是ArrayList
的容量.如果你想知道更多关于这个的知识,我建议你阅读这篇文章文章array
length vsArrayList
Size in Java
10) Dimension 维度
ArrayList
和array
的另外一个重要的区别就是array
可以使多维度的.例如,你可以设置一个二维数组或者三维数组.可以使你创在一个特殊的数据结构来代表矩阵或者2D形式(terrains
),另一方面,ArrayList
并不支持允许你指定维度.请参见这个指导来学习更多关于如何在Java里使用多维度的数组.
这里是列出了所有ArrayList
和array
的重要区别
Similarity betweenarray
andArrayListarray
和ArrayList
的相似点
目前为止你已经掌握ArrayList
和array
的区别,现在让我们集中他们的一些相似之处,由于ArrayList
内部使用的是array
,他们必然有很多相似之处,例如:
1) Data Structure 数据结构
两者都允许你存数对象,并且所有的都是基于index的数据结构,提供O(1)的复杂度来获取一个元素,但是如果通过二分查找来查询某个元素依旧需要log(N)的复杂度.
2) Order 顺序(没太理解这句话的意思)
Botharray
andArrayList
maintains order on which elements are added into them. (array
和ArrayList
都保持着元素的顺序?)
3) Search 查找
你可以通过index来查找一个元素,这个是O(1)的时间复杂度,除此之外如果你的array
不是排好序的数组你可以用线性的查找,这个将消耗大约O(n)的时间复杂度,或者你可以将数组排序后使用二分查找,这个将消耗排序的时间复杂度加上O(logN)
4) Null values 空值
array
和ArrayList
都允许存储null值,但请记住只有object的array
可以这样,基本类型的数组会存储他们的默认值,例如int型的数组默认存储0,boolean的数组默认存储false.
5) Duplicates 重复
array
和Arraylis都允许存储重复的值,
6) Performance 性能
ArrayList
模仿array
的性能,例如O(1)复杂度的访问元素如果你知道这个元素的index,但是ArrayList
会消耗更多的内存,因为它是存储的对象,并且持有了而外的数据来自动更改ArrayList
的长度.
7) Zero-based Index
这些就是关于array
和ArrayList
的所有不同点啦,其中你需要记住的最重要的不同点就是array
是静态的,你无法一旦创建了一个数组就无法更改它的大小,但是ArrayList
因为是动态的,所以它可以做到.根据这个不同点,如果你事先知道数组的长度,并且确定它的大小不会改变,你应该使用array
,否则请使用ArrayList
吧