数据结构--数组
一.线性和非线性
线性:除首尾外只有一个唯一的前驱和后继。eg:数组,链表等。
非线性:不是线性的就是非线性。
二.数组是什么?
数组是一个固定长度的存储相同数据类型的数据结构,数组中的元素被存储在一段连续的内存空间中。它是最简单的数据结构之一,大多数现代编程语言都内置数组支持。
三.数组的特性
1.存储类型一致。
数组的存储类型必须一致,在面向对象中,存在子类继承父类的情况,若存储的对象都继承于某一个父类,那么也可以判定为类型一致。
2.长度固定。
数组需要的是一个固定的连续的空间。
3.定义数组的方式。
int[] arr={}
int[] arr=new int[length];
int[] arr=new int[]{1,2,3,4,5}
4.通过索引查询数组中的元素
数组的索引从0开始,每个元素都对应着一个索引处的值。并且索引只能是 int 类型,不能为long更不能是其他的类型。所以数组的最大长度就是 int 的最大值。
5.索引的范围
由于数组的索引时从0开始,所以索引的范围就是从0-(length-1)
6.数组中常见的异常
(1)NullPointException 空指针异常:访问的数据不存在。
private int[] a;
public void test(){
a[1] = 3;
}
(2)ArrayIndexOutOfBoundsException 索引越界异常:索引不合理。
int[] arr=new int[5];
int a=arr[-1];
int b=arr[5];
7.常见的数组
字符串,对象数组,哈希表等。
四.数组的优势
数组存在索引,所以很方便查询,直接通过索引值调用get()返回即可。
五.数组的劣势
数组每一次在数组中间增删数据时,需要注意前后的元素,牵一发则动全身。
所以数组增删数据特别慢。
而且,数组的长度是固定的,不能动态改变。
六.动态数组
指一些拥有自动扩容能力的数组。eg:ArrayList,Vector。
1.Vector底层逻辑
底层是一个数组,使用构造器进行对数组长度的初始设置。在无参构造中调用有参构造。
所以在new Vector对象时,就已经创建好了一个长度为10的数组。
add()方法的底层逻辑以及自动扩容:
在自动扩容的方法中,如果触发自动扩容的条件,数组会自动将当前数组的长度作为参数传递过去,Vector的底层会重新new一个长度为之前数组2倍的新数组并将新数组重新赋给原数组来蒙混过关,让使用者以为还是之前那个数组,但是实质上已经不是之前那个数组,而是新数组了。
这种扩容的方式会存在一个缺陷:在每次扩容时,都会留下一个之前的旧数组,在Vector的底层是不会对这个数组进行处理的,而是等内存满了之后才会进行删除。
所以Vector牺牲的是空间,获得更多的存储空间。
2.ArrayList底层逻辑
ArrayList底层同样是数组,但是数组长度的设定和Vector有些不同的方面。
ArrayList的无参构造只是将一个空串赋值给了elementData数组:
所以 ArrayList 在new了对象之后,并不存在数组中有长度的情况,但是,ArrayList 恰恰就是这个小细节与Vector的差距就显现出来了。ArrayList会在第一次 add() 也就是第一次向数组中添加元素时,才会将数组的长度赋值为10。就是说用的时候才创建,这样就比Vector更节省空间一点。
ArrayList的自动扩容和Vector的底层逻辑基本一致,只有一点点不同的地方就是:ArrayList 是1.5倍扩容。
3.Vector和ArrayList的区别
本小节结束,谢谢大家观看学习!!