@[FAT-Remcal|从倔强青铜到最强王者]
数组与动态数组
摘要:
数组基本知识:数组是可以保存一组相同数据类型的一种数据结构;定义一个数组必须有固定的长度,且不能修改长度;数据拥有边界检查,尝试获取不在数组范围内的值时,会抛出异常(ArrayIndexOutOfBoundsException);数组是引用类型,存放在堆内存中;对象数组和基本数据类型数组在应用上是相同的,区别是对象数组保存的是引用,而基本类型数组保存的是值。
1.实现动态数组的步骤:
1.1 在添加元素时判断数组是否有空余空间;
1.2 如果有空余空间,则添加元素,完毕;
1.3 如果没有空余空间,跳转至1.4、1.5、1.6;
1.4 确定新数组的扩充方法;
1.5 创建新数组根据扩充后的长度;
1.6 把原数组中的数据复制到新数组中;
2.数组的几种常用操作:
2.1 添加元素(重要):可能造成现有数组长度不够,需要扩充,注意数组长度不能改变,只能重建一个数组;
2.2 删除元素(重要):由于数组是线性数据存储结构,通常需要确保元素的连续性,所以在被删除的元素非数组末尾时,我们通过需要把被删除元素之后的元素依次往前移动,以确保在末尾留出空余位置,这样也便于添加新元素时总是在末尾,查询遍历时也避免空指针;
2.3 更新元素:更新的是数组某个位置的值;
2.4 查找元素:在现有的数组基础之上查找;
3.动态数组的重要性:
3.1 动态数组变相解决了数组固定长度带来的问题;(不存在动态数组,是“动态”数组)
3.2 数组是存取效率最高的数据结构;(一种线性数据结构,通过下标操作,查询和存储效率都很高)
3.3 动态数组如果频繁扩充必然会带来性能的下降,产生垃圾数组对象;(任何算法都有优缺点(两面性),避免使用其缺陷,利用其优势是好的做法。但前提是掌握的多才有选择性。关键是要在动态数组的扩充次数和所存储的数据量之间找平衡做取舍)
3.4 数组不适合作删除插入等操作,适合添加,查找,遍历;(适合做删除插入的是链表(也是一种数据结构))
3.5 动态数组的实现原理被使用在ArrayList、Vector的集合类中;
3.6 面试题:手写实现ArrayList类;(考察对动态数组的原理的理解)
code1:
//添加:实现动态数组
public void add(Chicken c){
if(count>=cs.length){//数组已满,需要扩充
//算法1:扩充原来数组大小的一半 cs.length*3/2+1
//算法2:扩充原来数组的一倍 cs.length*2
int newLen = cs.length*2;
cs = Arrays.copyOf(cs,newLen);
}
cs[count] = c;
count++;
}
code2:
//删除
public void delete(int id){
for(int i=0;i<count;i++){
if(cs[i].getId()==id){
//找到了要删除的对象,把该对象之后的对象向前移动一位
for(int j=i;j<count-1;j++){
cs[j] = cs[j+1];
}
//把最后一个对象赋值为空(删除)
cs[count-1] = null;
count--;//下标减一
break;
}
}
}
引申问题:
1.Java中的代码运行一次之后,变量和值都消失了么?是立刻消失的么?