爲了鍛鍊思路,鞏固之前學的簡單知識,試着自己寫一下ArrayList類。
用數組來實現ArrayList類。ArrayList類和數組很像,但是數組是定長不可改的,ArrayList不定長。
目錄
構造MyArrayList類
我用了泛型來構造
package MyArrayList;
/**
* 自己寫的ArrayList類
*
* @author july
*
* @param <T> 泛型
*/
class MyArrayList<T> {
private T[] array; // 本質是對數組的操作
private int index=0; // 記錄當前最後一個元素的下標
/**
* 無參構造方法
*/
MyArrayList() {
array = (T[]) new Object[10]; // 創建泛型數組,初始長度設爲10
}
/**
* 有參構造方法
*
* @param size 存儲長度
*/
MyArrayList(int size) {
array = (T[]) new Object[size];
}
}
爲了方便之後的操作,這裏寫兩個方法。一個是用於規範其輸出格式的toString()方法,一個是類私有的設置集合當前最後一個元素的下標的方法setIndex()
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[");
for (T obj : array) {// 循環遍歷數組
if (obj == null)
break;
sb.append(obj);
sb.append(",");
}
// 去除最後一個逗號
sb.deleteCharAt(sb.length() - 1);
sb.append("]");
return sb.toString();
}
/**
* 設置數組的最後一個元素的下標值
*/
private void setIndex() {
for (int i = 0; i < array.length; i++) {
if (array[i] == null) {
index = i - 1; // 記錄下最後一個元素的下標
break;
}else {
index=i;//全滿時候
}
}
}
添加操作add()
我重載了兩個添加操作方法,一個是直接添加到末尾,一個是插入操作,插入到某個下標位置。書寫時候需要考慮用於實現的數組是否已經滿了,如果滿了,則需要創建新的更大的數組進行操作。
添加操作:
/**
* 增加元素操作,增加到末尾
*
* @param object
* @return
*/
void add(T object) {
//獲取當前數組最後一個下標
setIndex();
if (index == array.length-1) { // 數組滿了,需要創建新數組
T[] temp = (T[]) new Object[array.length * 2]; // 創建新數組
System.arraycopy(array, 0, temp, 0, array.length); // 複製數組
// 將array指向新創建的數組
array = temp;
// 重新給index賦值爲當前可以插入元素的下標
setIndex();
}
// 插入元素到數組末尾位置
array[index+1] = object;
}
插入操作:
/**
* 插入操作
* @param desIndex 插入位置
* @param obj 插入元素
*/
void add(int desIndex,T obj) {
//先判斷下標是否越界
setIndex();
if(desIndex>index+1) {//最後一個位置也可以插入
try {
throw new Exception("下標越界");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if(desIndex == index+1) {
//插入到末尾
add(obj);
}else {
//在前面的其他位置插入元素
for(int i=index;i>=desIndex;i--) {
//先把元素向後移動一位,空出需要插入的位置
array[i+1]=array[i];
}
//可以插入元素了
array[desIndex]=obj;
}
}
測試類:
package MyArrayList;
//測試自己寫的ArrayList類
public class TestMyArrayList {
public static void main(String[] args) {
//創建整型ArrayList
MyArrayList<Integer> myInt=new MyArrayList<Integer>();
myInt.add(0);
myInt.add(1);
myInt.add(2);
myInt.add(3);
myInt.add(4);
myInt.add(5);
System.out.println(myInt.toString());
//創建字符型的ArrayList
MyArrayList<String> myChar=new MyArrayList<String>();
myChar.add("a");
myChar.add("b");
myChar.add("c");
myChar.add("d");
myChar.add("e");
myChar.add("f");
myChar.add("g");
System.out.println(myChar.toString());
}
}
插入操作的效果:
myInt.add(0, -1);
myChar.add(0, "start");
刪除操作remove()
刪除操作我重載了兩種,一種是刪除某個下標的值,另一個是根據值查找然後刪除。刪除某位置的元素後要把後面的部分往前移動佔掉空的位置
根據下標刪除:(需要注意下標是否越界)
/**
* 刪除操作
*
* @param desIndex 需要刪除的元素下標
*/
void remove(int desIndex) {
if (array[desIndex] == null) {
// 該下標位置沒有值
try {
throw new Exception("該位置沒有值,無法進行刪除操作");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
array[desIndex] = null; // 先刪除該處的值
for (int i = desIndex; i <= index; i++) { // 移動後面的值,填補刪除的地方
array[i] = array[i + 1];
}
// 把最後一個位置置空
array[index + 1] = null;
}
}
根據值查找來刪除:(需要注意該值是否存在)
這裏使用了自己寫的查找函數(寫在下面了)
/**
* 刪除操作 注:如果有多個相同的元素,只刪除第一個
*
* @param obj 需要刪除的元素
*/
void remove(T obj) {
// 調用查找方法尋找該值的下標
int i = search(obj);
if (i != -1) {
remove(i); // 直接調用前面方法來刪除
} else {
// 沒有找到
try {
throw new Exception("沒有找到該元素");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
查看效果:
//根據下標刪除
myInt.remove(4);
myChar.remove(4);
//根據值查找刪除
myInt.remove((Integer)14);
myChar.remove("f");
(坑)注意:因爲第一個對象myInt將泛型使用成Integer了,直接寫14會自動調用第一個remove方法(根據下標),將拋出異常下標越界,需要顯式將int轉爲Integer纔可以使用。
查找操作search()
根據值查找,返回下標。若沒有找到,返回-1
/**
* 查找
*
* @param object 需要查找的元素
* @return 元素所在下標,若沒有找到,返回-1
*/
int search(T object) {
for (int i = 0; i < array.length; i++) {
if (array[i] == object) {
return i;
}
}
return -1;
}
效果查看:
System.out.println(myInt.search(14));
System.out.println(myChar.search("z"));
修改操作set()
修改也重載了兩種,一種修改某下標的值,一種是傳入原值,經過查找修改成新的值
/**
* 修改操作
* @param desIndex 需要修改的下標
* @param obj 修改目標元素
*/
void set(int desIndex,T obj){
//首先判斷該下標是否越界
setIndex();
if(desIndex>index) {
try {
throw new Exception("下標越界");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
array[desIndex]=obj;
}
}
/**
* 修改操作
* @param oObj 需要修改的元素值
* @param dObj 修改後的元素值
*/
void set(T oObj,T dObj) {
int i=search(oObj);
if(i==-1) {
//沒有找到這個元素
try {
throw new Exception("沒有找到這個元素");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
array[i]=dObj;
}
}
查看效果:
//根據下標修改
myInt.set(4, (Integer)4);
myChar.set(0, "A");
//根據值查找修改
myInt.set((Integer)14, (Integer)4);
myChar.set("z", "A");
(順便試了一下越界的異常)
好了,暫時就這些!