1.什么是数组队列
要知道这个问题,首先我们要清楚数组有哪些特点。
数组的优点是显而易见的,但是数组有哪些缺点呢?
其中我认为最大的一个缺点就是数组大小固定,如果要存储的数据个数不确定的时候?就可能出现以下两种情况:
1.数组空间不够,导致越界异常发生
2.如果空间太大了,数据不够,就会浪费内存空间
那如何解决这个问题呢,或许数组队列可以很好的解决这个问题。
2队列的简单实现
我们先实现一个简单的队列,这个队列能解决的问题就是数组大小固定这个问题。我们以学生信息管理为例:
首先我们需要一个学生类;
/* 定义Student学生类 */
public class Student {
/*定义学生的四个属性*/
public int score;
protected char sex;
int age;
private String name;
public Student(int score, char sex, int age, String name) {
this.score = score;
this.sex = sex;
this.age = age;
this.name = name;
}
public String toString() {
return "姓名:" + name + "\t年龄:" + age + "\t性别:" + sex + "\tr学分:" + score;
}
// 如果属性的访问修饰符不是public,则要给属性定义public的get和set方法
// 定义设置姓名属性值的方法
public void setName(String n) {
name = n;
}
// 定义获取姓名属性值的方法
public String getName() {
return name;
}
// 省略了sex和age的get和set方法。
}
这样我们一个学生类就定义好了。然后我们就要实现队列,看下面代码:
public class ArrayList {
private Student [] array = null; //声明学生类型的数组名属性
private int size = 0; //声明记录数组队列中存储的元素个数属性
/**
* 构造方法
*/
public ArrayList() {
array = new Student [0];// 实例化数组对象,长度为0
}
/**
* 构造方法
* @param length要创建新数组的大小
*/
public ArrayList(int length) {
array = new Student[length];// 实例化数组对象,长度为length
}
/**
* 实现add方法,向队列中加入一个学生对象
*/
public void add(Student stu) {
// 判断数组长度是否为0或者数组中已经存满数据
if (array.length == 0 || array.length == size) {
// 创建一个新的数组对象,长度array数组的长度+1
Student[] newArray = new Student[array.length + 1];
// 把array数组中的数据存入newArray数组中
for (int i = 0; i < array.length; i++) {
newArray[i] = array[i];
}
array = newArray;// 交换首地址,指向新建的数组
}
array[size++] = stu;// 将数据存入到array数组中
}
/**
* 获取指定索引位置的数据
* @param index要获取索引位置的数据
* @return 返回对应索引位置的数据,如果index越界则返回null。
*/
public Student get(int index) {
if (index < 0 || index >= size)
return null;
return array[index];
}
/**
* 获取数组队列中存储的元素总数
* @return 返回size属性值
*/
public int size() {
return size;
}
}
这样一个简单队列的实现就完成了,这个队列能在学生个数不确定情况下,存储学生的数据。接下来就是我们就要测试一下这个队列了:
import java.util.Random;
public class Manage {
public static void main(String[] args) {
ArrayList mal = new ArrayList(10);
Random rand = new Random();
int size = rand.nextInt(59)+1;//随机产生一个0到60的数
for (int i = 0; i < size; i++) {
Student stu = new Student(rand.nextInt(100), rand.nextInt(2) == 0 ? '男' : '女',
rand.nextInt(10) + 17,"姓名" + ((char) (rand.nextInt(26) + 65)));
mal.add(stu);
}//创建学生对象,并给对象赋初值,并且保存到数组队列中
/**
* 打印队列中每个学生对象的信息
*/
System.out.println(mal.size()+"个学生信息如下:");
for (int i = 0; i < mal.size(); i++) {
Student stu = mal.get(i);//调用get方法,得到队列中指定位置的数据
System.out.println(stu.toString());//输出指定位置的数据
}
}
}
运行结果:
3队列的简单完善(泛型)
上面的队列最大的缺点就是,只能放入Student类(或其子类)的对象,这就很麻烦了,因为如果我们要存储其他的对象的时候,我们又要重新创建一个队列。对于这种问题,java中的"泛型"语法就能很好的解决这个问题。首先我们需要改变队列的定义,并可以将Student对象换成Object,并将所有的引用数据类型用代替。
泛型的特点:
(1)泛型(、<K、V>、、…) 不是Java中的一种数据类型。只是一个特殊的符号,可以在你不确定要存储什么类型的数据时,用这个符号代替Java中所有的数据类型。
(2)当你使用的时候,你可以用对应的数据类型来代替这个符号,这样就只能存储你指定的这一种数据类型;如果你不指定,则任意一种数据类型都可以存储。
看下面代码:
先定义一个Teacher类
public class Teacher {
public String name;
public Teacher(String name) {
this.name = name;
}
public String toString() {
return "老师" + name;
}
}
队列中的实现(注意泛型的使用):
public class ArrayList<E> { // <E>声明数组队列支持泛型
private Object [] array = null; //声明Obeject类型的数组名属性
private int size = 0; //声明记录数组队列中存储的元素个数属性
/**
* 构造方法
*/
public ArrayList() {
array = new Object [0];// 实例化数组对象,长度为0
}
/**
* 构造方法
* @param length要创建新数组的大小
*/
public ArrayList(int length) {
array = new Object[length];// 实例化数组对象,长度为length
}
/**
* 实现add方法,向队列中加入一个指定类型的对象
*/
public void add(E stu) {
// 判断数组长度是否为0或者数组中已经存满数据
if (array.length == 0 || array.length == size) {
// 创建一个新的数组对象,长度array数组的长度+1
Object [] newArray = new Object [array.length + 1];
// 把array数组中的数据存入newArray数组中
for (int i = 0; i < array.length; i++) {
newArray[i] = array[i];
}
array = newArray;// 交换首地址,指向新建的数组
}
array[size++] = stu;// 将数据存入到array数组中
}
/**
* 获取指定索引位置的数据
* @param index要获取索引位置的数据
* @return 返回对应索引位置的数据,如果index越界则返回null。
*/
public E get(int index) {
if (index < 0 || index >= size)
return null;
return (E) array[index];
}
/**
* 获取数组队列中存储的元素总数
* @return 返回size属性值
*/
public int size() {
return size;
}
}
接下来测试一下这个队列能不能存两个不同对象的信息:
import java.util.Random;
public class Manage {
public static void main(String[] args) {
//创建队列对象:只能放入Student类型对象的队列
ArrayList<Student> mal = new ArrayList<Student>(10);
Random rand = new Random();
int size = rand.nextInt(59)+1;//随机产生一个0到60的数
for (int i = 0; i < size; i++) {
Student stu = new Student(rand.nextInt(100), rand.nextInt(2) == 0 ? '男' : '女',
rand.nextInt(10) + 17,"姓名" + ((char) (rand.nextInt(26) + 65)));
mal.add(stu);
}
/**
* 打印队列中每个学生对象的信息
*/
System.out.println(mal.size()+"个学生信息如下:");
for (int i = 0; i < mal.size(); i++) {
Student stu = mal.get(i);//调用get方法,得到队列中指定位置的数据
System.out.println(stu.toString());//输出指定位置的数据
}
//创建队列对象:只能放入Teacher类型对象的队列
ArrayList<Teacher> altc = new ArrayList<Teacher>(10);
int s = rand.nextInt(19)+1;//随机产生一个0到20的数
for (int j = 0; j < s; j++) {
Teacher teac = new Teacher("姓名" +((char) (rand.nextInt(26) + 65)));
altc.add(teac);
}
/* 打印队列中每个学生对象的信息*/
System.out.println(altc.size()+"个老师信息如下:");
for (int i = 0; i <altc.size(); i++) {
Teacher teac = altc.get(i);//调用get方法,得到队列中指定位置的数据
System.out.println(teac.toString());//输出指定位置的数据
}
}
}
代码运行结果:
这样一个简单的队列基本就完成了,不过这个队列还有许多的不足之处有待完善,首先,没加入一个对象,都要创建一个数组,能不能多预留一些空间,预留多少空间呢?另外我们如何对队列中指定位置的数据进行插入和删除等等。这些都是我们可以进一步优化这个队列的地方。