数组
数组(Array)是一种用连续的内存空间存储相同数据类型数据的线性数据结构。
数组如何获取其他元素的地址值?
寻址公式:a[i]= baseAddress +i* dataTypeSize
●baseAddress:数组的首地址
●dataTypeSize:代表数组中元素类型的大小,int型的数据,dataTypeSize=4个字节
为什么数组索引从0开始呢?假如从1开始不行吗?
如果从0开始寻址公式为:
alil= baseAddress + (i-1)* dataTypeSize
这样对于cpu来说,增加了一个减法指令,这样不如从0开始效率高
1.随机查询(根据索引查询)
数组元素的访问是通过索引来访问的,计算机通过数组的首地址和寻址公式能够很快速的找到想要访问的元素,因此通过索引查找数据中的元素时间复杂度为O(1)。
2.未知索引查询
查找排序后数组内的元素,可以使用二分查找,时间复杂度就为O(logn)
3、操作数组的时间复杂度(插入、删除)
数组是一段连续的内存空间,因此为了保证数组的连续性会使得数组的插入和删除的效率变的很低。因为如果从中间插入或者删除元素,后面的元素都会进行移动。
最好情况下是O(1)的,最坏情况下是O(n)的,平均情况下的时间复杂度是O(n)。
ArrayList
ArrayList底层的实现原理是什么?
ArrayList底层是用动态的数组实现的
ArrayList初始容量为0,当第一次添加数据的时候才会初始化容量为10
ArrayList在进行扩容的时候是原来容量的1.5倍,每次扩容都需要拷贝数组
ArrayList在添加数据的时候
确保数组已使用长度(size)加1之后足够存下下一个数据
计算数组的容量,如果当前数组已使用长度+1后的大于当前的数组长度,则调用grow方法扩容 (原来的1.5倍)确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。
返回添加成功布尔值。
面试有可能会问ArrayList list=new ArrayList(10)中的list扩容几次
其实这个时候只是声明了一个ArrayList,指定了容量为10,未扩容。
面试可能会问如何实现数组和List之间的转换
参考回答:
数组转List ,使用JDK中java.util.Arrays工具类的asList方法List转数组,使用List的toArray方法 无参toArray方法返回Obiect数组,传入初始化长度的数组对象,返回该对象数组
面试官再问:
用Arrays.asList转List后,如果修改了数组内容,list受影响吗?List用toArray转数组后,如果修改了List内容,数组受影响吗?
再答:
Arrays.asList转换list之后,如果修改了数组的内容,list会受影响因为它的底层使用的Arrays类中的一个内部类ArrayList来构造的集合,在这个集合的构造器中,把我们传入的这个集合进行了包装而已,最终指向的都是同一个内存地址。
list用了toArray转数组后,如果修改了list内容,数组不会影响,当调用了toArray以后,在底层是它是进行了数组的拷贝,跟原来的元素就没啥关系了,所以即使list修改了以后,数组也不受影响