我們知道 ArrayList 是一個集合,它能存放各種不同類型的數據,而且其容量是自動增長的。那么它是怎么實現的呢?
其實 ArrayList 的底層是用 數組實現的。我們查看 JDK 源碼也可以發現。而用數組實現集合的原理有兩點:
1、能自動擴容
2、能存放不同類型的數據
這兩點我們是這樣解決的:
1、當一個數據存放滿了,我們就將這個數據復制到一個新的數組中,而這個新的數組容量要比原數組大。通過這樣不斷的擴大數組長度,也就是集合的容量。那么這里我們用到了這個方法 System.arraycopy
完整的寫法為:public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
參數
@ src -- 這是源數組 @ srcPos -- 這是源數組中的起始位置 @dest -- 這是目標數組 @ destPos -- 這是目標數據中的起始位置 @ length -- 這是一個要復制的數組元素的數目
int arr1[] = {0,1,2,3,4,5}; int arr2[] = {0,10,20,30,40,50}; System.arraycopy(arr1,0,arr2,1,2); //結果為:arr2 = [0,0,1,30,40,50];
2、第二個問題,我們只需要聲明為 Object 類型的數組就可以了。
完整代碼如下:
package com.ys.collection; public class MyArrayList { //用於存儲數據 private transient Object[] data = null; //集合的元素個數 private int size = 0; //定義一個常量為 10.(后面用於定義默認的集合大小) private static final int DEFAULT_CAPACITY = 10; /*** * 有參構造函數 * 指定數組的大小 * @param length */ public MyArrayList(int initialCapacity){ if(initialCapacity < 0){ throw new IllegalArgumentException("非法的集合初始容量值 Illegal Capacity: "+ initialCapacity); }else{ //實例化數組 this.data = new Object[initialCapacity]; } } /*** * 無參構造函數 * 指定數組的初始大小為 10 */ public MyArrayList(){ this(DEFAULT_CAPACITY); } /*** * 1、復制原數組,並擴容一倍 * 2、復制原數組,並擴容一倍,並在指定位置插入對象 * @param index * @param obj */ public void checkIncrease(int index,Object obj){ if(size >= data.length){ //實例化一個新數組 Object[] newData = new Object[size*2]; if(index == -1 && obj == null){ System.arraycopy(data, 0, newData, 0, size); }else{ //將要插入索引位置前面的對象 拷貝 System.arraycopy(data, index, newData, index+1, size-index); } //將 newData 數組賦值給 data數組 data = newData; newData = null; } } /*** * 獲取數組的大小 * @return */ public int getSize(){ return this.size; } /*** * 根據元素獲得在集合中的索引 * @param o * @return */ public int indexOf(Object o) { if (o == null) { for (int i = 0; i < data.length; i++) if (data[i]==null) return i; } else { for (int i = 0; i < data.length; i++) if (o.equals(data[i])) return i; } return -1; } /*** * 在尾部添加元素 * @param obj * @return */ public boolean add(Object obj){ //檢查是否需要擴容 checkIncrease(-1, null); data[size++] = obj; return true; } /** * 判斷給定索引是否越界 * @param index * @return */ public boolean checkIndexOut(int index){ if(index > size || index < 0){ throw new IndexOutOfBoundsException("指定的索引越界,集合大小為:"+size+",您指定的索引大小為:"+index); } return true; } public boolean add(int index,Object obj){ //如果給定索引長度剛好等於原數組長度,那么直接在尾部添加進去 if(index == size){ add(obj); } //checkIndexOut()如果不拋異常,默認 index <=size,且 index > 0 else if(checkIndexOut(index)){ if(size < data.length){ System.arraycopy(data, index, data, index+1, size-index); data[index] = obj; }else{ //需要擴容 checkIncrease(index, obj); } size++; } return true; } /*** * 根據索引獲得元素 * @param index * @return */ public Object get(int index){ checkIndexOut(index); return data[index]; } /*** * 刪除所有元素 */ public void removeAll(){ for(int i = 0 ; i < data.length ; i++){ data[i] = null; } } /*** * 根據索引刪除元素 * @param index * @return */ public Object remove(int index){ if(index == size+1){ throw new IndexOutOfBoundsException("指定的索引越界,集合大小為:"+size+",您指定的索引大小為:"+index); }else if(checkIndexOut(index)){ //保存對象 Object obj = data[index]; if(index == size){ data[index] = null; }else{ //將后邊的數組向前移動一位 System.arraycopy(data, index+1, data, index, size-index); } size--; return obj; } return null; } /*** * 刪除指定的元素,刪除成功返回 true,失敗返回 false * @param obj * @return */ public boolean remove(Object obj){ for(int i = 0 ; i < size ; i++){ if(obj.equals(data[i])){ remove(i); return true; } } return false; } /*** * 在指定位置修改元素,通過索引,修改完成后返回原數據 * @param index * @param obj * @return */ public Object change(int index,Object obj){ checkIndexOut(index); Object oldObj = data[index]; data[index] = obj; return oldObj; } /*** * 查看集合中是否包含某個元素,如果有,返回 true,沒有返回 false * @param obj * @return */ public boolean contain(Object obj){ for(int i = 0 ; i < data.length ; i++){ if(obj.equals(data[i])){ return true; } } return false; } public static void main(String [] args){ MyArrayList my = new MyArrayList(); //System.out.println(my.data.length); my.add(0,3); //System.out.println(my.getSize()); my.add(0,4); //System.out.println(my.getSize()); my.add(0,5); //my.removeAll(); //my.remove(2); //System.out.println(my.get(2)); System.out.println(my.indexOf(null)); System.out.println(my.contain(2)); for(int i = 0 ; i < my.data.length ; i++){ System.out.println(my.data[i]); } } }