一、数组的原理和特点;
数组:一组能够存储相同数据类型的变量的集合。
当我们有一组相同类型的数据需要存储,如果此时使用单个变量,我们需要定义N个变量,这样做的话会非常繁琐且不利于后期代码的维护。
特点:
1、数组是可以保存一组相同数据类型的一种数据结构
2、定义一个数组必须有固定的长度,且不能修改长度
3、数组拥有边界检查,尝试获取不在数组范围内的值时,会出现数组下标越界异常(ArrayindexOutOfBoundsException)
4、数组是引用类型,会存储在堆内存中。
5、对象数组和基本数据类型数组在使用上是相同的,区别是对象数组保存的是引用,基本类型的数组是保存基本类型的值。
二、动态数组的概念;
动态数组是指一个数组的长度可以动态进行扩充,目的是在数组元素存储满后可以继续存储,已达到“无限”长度。
PS:问题;前面数组特点里提到过,数组在定义时就必须固定长度,且不能修改长度,这显然与动态数组相违背。
解决方法;
1、重新创建一个数组,长度在原数组基础上扩容,放弃原数组
2、把原数组中的元素复制到新数组。
三、手动实现动态数组方法;
具体步骤如下;
1、在添加元素时判断数组是否有空余空间;
2、如果有,则添加元素;
3、反之,跳转到下一步;
4、确定新数组的扩充算法;
5、创建新数组根据扩容后的长度;
6、把原数组中的数据复制到新数组中。
(如图所示)
删除元素;
由于数组是线性数据存储结构,通常需要确保元素的连续性,所以在被删除的元素非数组末尾时,我们需要把被删除元素之后的元素依次向前移动一位,以确保在末尾留出空余位置,这样也便于添加新元素时总是在末尾,查询遍历时也避免空指针异常。
四、动态数组的重要性;
1、动态数组变相解决了数组固定长度带来的问题;
2、数组是存取效率最高的数据结构;
3、动态数组如果频繁扩充必然带来性能下降,产生垃圾数组对象;
4、数组不适是做 删除插入 等操作,适合 添加、 查找、 遍历;
5、动态数组的实现原理被使用在ArrayList、Vector的集合中
6、面试题 ‘手动实现ArrayList类’
动态数组的 应用
Demo:模拟小鸡管理系统(增删改查)
import java.util.Arrays;
public class MyArraysList {
public static void main(String[] args) {
MyArraysLists ma=new MyArraysLists(5);
//添加操作
ma.add(new Chicken(1,12,"小白"));
ma.add(new Chicken(4,10,"小红"));
ma.add(new Chicken(6,14,"小蓝"));
ma.add(new Chicken(2,18,"小紫"));
ma.add(new Chicken(5,8,"小黑"));
ma.add(new Chicken(3,16,"小绿"));
System.out.println("==============添加完毕==============");
//输出所有信息
ma.printAll();
System.out.println("当前对象数组的长度为:"+ma.length());
System.out.println("==============删除==============");
ma.delete(4);
ma.printAll();
System.out.println("==============修改==============");
ma.update(new Chicken(2,3,"小宝"));
ma.printAll();
System.out.println("==============查找==============");
Chicken c = ma.find(2);
c.print();
}
}
//管理对象的类
class MyArraysLists{
//需要管理的数组
private Chicken[] cs=null;
//对象数组中元素的个数
private int count = 0;
public MyArraysLists(int size) {
if(size>0) {
cs = new Chicken[size];
}else {
cs = new Chicken[5];
}
}
//表示返回数组长度
public int length() {
return cs.length;
}
//数组中有多少个元素
public int size(){
return count;
}
//添加管理
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++;
}
//查找管理
public Chicken find(int id) {
for(int i=0;i
if(cs[i].getId()==id) {
return cs[i];
}
}
return null;
}
//删除管理
//1、先查到要删除的元素(确定要删除的元素)
//2、依次把要删除元素的后一个元素往前移动(覆盖)
//3、把最后一个元素设置为null
public void delete(int id) {
for(int i=0;i
//循环遍历,找到了对象,把该对象之后的对象向前移动一位
if(cs[i].getId()==id) {
for(int j=i;j
cs[j]=cs[j+1];
}
cs[count-1]=null;//把最后一个对象赋值为空
count--;//下标减减
break;//跳出循环
}
}
}
//更新管理
//修改元素(Chicken(id,age,name),id是作为要修改的对象的id,用于作为条件,
//age,name是作为新的值)
public void update(Chicken c) {
Chicken temp=find(c.getId());
if(temp!=null) {
temp.setName(c.getName());
temp.setAge(c.getAge());
}
}
//输出信息
public void printAll() {
for(int i=0;i
cs[i].print();
}
}
}
//用来测试的对象(小鸡类)
class Chicken{
private int id;//编号
private int age;//年龄
private String name;//名字
public Chicken(int id, int age, String name) {
super();
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void print() {
System.out.println("ID="+id+",age="+age+",name="+name);
}
}