在實現畫圖板時需要使用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;
}