在实现画图板时需要使用ArrayList,要求自己实现,只实现了画图板现阶段需要的功能与一些基础功能,很粗糙,还没有考虑优化。
20190124第一次更新
在动手实现之前,首先考虑我们需要什么功能?
计算机显示图像只显示最顶层的(即我们眼睛所能看到的部分),底层的图像拖到顶层时会从显存里读取图像的数据重新加载,这就要求我们存储相应的数据。画图板同理,它需要存放所画的图形数据,以便在需要的时候将其加载到屏幕上,所以我们的画图板需要一个可以存放图形数据的数组,可以往里面添加图形,也可以删除图形。在画图时并不确定会画多少图形,因此数组大小是可以自动变化的。
知道了需求,下面就根据需求手动实现ArrayList,我们可以称之为MyArrayList
存入数组的对象不确定,可能是直线,也可能是圆,因此需要用到泛型,如下所示
public class MyArrayList<E>{
……
}
要求数组大小可以根据画的图形数量自动变化,那么我们需要统计往数组里实际放了多少个数据(count)、数组的初始容量(initCapatity)、数组容量的增量(increment),此外还需一个可以存放任意对象的数组Object[] src
public class MyArrayList<E> {
int count = 0;
// 数组初始大小为10
int initCapatity = 10;
// 增量
int increment;
Object[] src;
}
通过new一个对象的方式获取数组,有两种方式,一个是用无参的构造方法,一个有参的构造方法,参数为初始数组大小,增量都为初始大小的一半
public MyArrayList () {
increment = (int)(initCapacity * 0.5);
src = new Object[initCapacity];
}
public MyArrayList(int initCapacity) {
this.initCapacity = initCapacity;
increment = (int)(initCapacity * 0.5);
src = new Object[initCapacity];
}
每画一个图形就要添加一个数据,因此要有add方法
/**
* 在数组末尾增加一个数据
*
* @param data 要增加的数据
*/
public void add(E data) {
// 如果传入数据的数量大于数组容量,则新建数组,增量为increment
if (count >= src.length) {
Object[] dest = new Object[src.length + increment];
// 使用native方法,提高效率
System.arraycopy(src, 0, dest, 0, src.length);
src = dest;
}
src[count++] = data;
}
另外有一些ArrayList需要实现的基本方法
/**
* 在指定下标位置添加一个数据
*
* @param index 要添加数据的位置
* @param data 要添加的数据
*/
public void add(int index, E data) {
Object[] dest;
if (count >= src.length) {
dest = new Object[src.length + increment];
System.arraycopy(src, 0, dest, 0, index);
System.arraycopy(src, index, dest, index + 1, src.length - index);
} else {
dest = src;
System.arraycopy(src, 0, dest, 0, index);
System.arraycopy(src, index, dest, index + 1, count - index);
}
src = dest;
src[index] = data;
count++;
}
/**
* 删除指定的数据,如果有多个相同的数据,则删除第一个
*
* @param data 要删除的数据
*/
public void delete(E data) {
Object[] dest = src;
int i;
for (i = 0; i < count; i++) {
if (src[i] == data) {
break;
}
}
System.arraycopy(src, 0, dest, 0, i);
System.arraycopy(src, i + 1, dest, i, count - 1 - i);
dest[count - 1] = null;
src = dest;
count--;
}
/**
* 删除指定的数据,根据参数isAll来确定是否删除所有与指定数据相同的数据
*
* @param data 要删除的数据
* @param isAll 是否删除删除所有与指定数据相同的数据
*/
public void delete(E data, boolean isAll) {
if (isAll == false) {
this.delete(data);
} else {
Object[] dest = src;
int tempCount = 0;// 临时计数器,记录要删除的元素的个数
for (int i = 0, j = 0; i < count; i++, j++) {
if (src[i] == data) {
dest[j] = src[i + 1];
i++;
tempCount++;
} else {
dest[j] = src[i];
}
}
for (int i = count - tempCount; i < count; i++) {
dest[i] = null;
}
src = dest;
count -= tempCount;
}
}
/**
* 删除指定下标位置的元素
*
* @param index 要删除元素的下标
*/
public void delete(int index) {
Object[] dest = src;
System.arraycopy(src, 0, dest, 0, index);
System.arraycopy(src, index + 1, dest, index, count - index - 1);
dest[count - 1] = null;
src = dest;
count--;
}
/**
* 根据下标更新元素
* @param index 要更新的元素下标
* @param data 新元素
*/
public void update(int index, E data) {
src[index] = data;
}
/**
* 根据下标获取对应位置的元素
*
* @param index 要取出的元素下标
*/
public E get(int index) {
return (E) src[index];
}
/**
* 获取数组的元素个数
*
* @return 返回元素个数
*/
public int size() {
return count;
}