上次我们对自定义数组进行了第一次优化,解决了数组添加数据速度慢的问题,但是数组还存在缺陷:只能添加事先规定的一类数据,而不能根据需求添加不同类型的数据。今天我们利用泛型优化自定义动态数组。
要想数组可以添加所有类型的数据,就必须改变数组的类型。之前的知识告诉我们:Object是Java中所有类的父类,如果把数组类型设置为Object,那么数组就可以容纳任何的数据。这里需要注意一个细节:理论上Object类型的数组只能保存引用类型,但所有的基本类型都不是引用类型,之所以能将基本类型的数据添加进Object数组中,是因为添加时基本数据类型会自动转变成对应的包装类。综上所述,我们只需要将数组类型和方法中数据data的类型改成Object就可以添加任何类型的数据了!
效果如下图:
但是我们又遇到了一个问题:如果一个数组什么类型的数据都能随意添加进去,数组就会变得很凌乱,不利于数据的分类保存,所以我们希望能够让数组根据输入的内容只能添加一种类型,这是就要用到泛型的内容。
我们需要在类ArrayList后面加上一个尖括号<>,表示该类为泛型,里面需要填写名字,一般命名为T、E、K、V等(需要有语义)。数组类型依然为Object不变,但需要把方法的参数里的data类型改为对应的名字,表示只能是这个类型的数据添加到数组中。
代码
//尖括号表示泛型,目的是实现只能添加一种元素的功能。
//尖括号里的数据类型只能是包装类,不能是基本数据类型
public class ArrayList<E> {
public Object[] Arr;
private static int length = 10;
//定义一个变量保存数组中的有效数据个数
private int size;
//使用构造方法写两个数组的使用方法
public ArrayList() {
//默认数组的长度为10
Arr = new Object[length];
}
public ArrayList(int len) {
//手动定义数组的初始长度
Arr = new Object[length];
}
//末尾添加数据
public void add(E data) {
//判断是否需要扩容
if (size == Arr.length) {
//两倍扩容数组
Object[] nArr = new Object[Arr.length * 2];
for (int i = 0; i < Arr.length; i++) {
nArr[i] = Arr[i];
}
//更改内存地址
Arr = nArr;
}
//数据添加到末尾
Arr[size] = data;
size++;
}
//插入数据
public void add(E data, int index) {
//判断数组是否需要扩容
if (size == Arr.length) {
//两倍扩容数组
Object[] nArr = new Object[Arr.length * 2];
//从index 位置开始,把后面的数据往后移动
for (int i = 0; i < index; i++) {
nArr[i] = Arr[i];
}
for (int i = index; i < Arr.length; i++) {
nArr[i + 1] = Arr[i];
}
Arr = nArr;
Arr[index] = data;
size++;
} else if (size < Arr.length) {
for (int i = index; i < size; i++) {
Arr[i + 1] = Arr[i];
}
Arr[index] = data;
size++;
}
}
//获取指定位置的数据
public E get(int index) {
if (index < 0 || index > Arr.length) {
System.out.println("下标越界!!!");
return null;
} else {
return (E)Arr[index];
}
}
//移除指定位置的数据
public E remove(int index) {
Object removeData = Arr[index];
for (int i = index; i < size; i++) {
Arr[i] = Arr[i + 1];
}
size--;
return (E)removeData;
}
//移除指定的数据
public boolean removes(E data) {
boolean gs=false;
for (int i = 0; i < Arr.length; i++) {
if (Arr[i]==data ) {
remove(i);
gs= true;
}
}
return gs;
}
//获得数组的长度
public int getSize() {
return Arr.length;
}
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
//添加整型数据
list.add(1);
list.add(2);
list.add(3);
list.add(5);
list.add(6);
list.add(7);
list.add(8);
list.add(9);
list.add(10);
list.add(11);
list.add(4, 3);
list.removes(2);
for (int i = 0; i < list.size; i++) {
System.out.print(list.get(i) + " ");
}
}
}
这样,我们就能实现只能在数组中添加同一种数据的功能了!
补充知识
1、泛型
在Java中,我们用尖括号<>表示泛型,可以把添加到动态数组(集合)中的类型参化,里面需要输入引用类型或者基本类型对应的包装类。将基本数据类型变成包装类的过程叫做装箱。
作用:限制必须是同类型的数据才能添加到同一个集合对象中。
2、基本数据类型及其对应的包装类
基本数据类型 | 对应的包装类 |
---|---|
byte(整型) | Byte |
short(整型) | Short |
int(整型) | Integer |
long(整型) | Long |
float(浮点型) | Float |
double(浮点型) | Double |
char(字符) | Character |
boolean(布尔型) | Boolean |