ArrayList是基于數(shù)組實(shí)現(xiàn)的嗎?
ArrayList相關(guān)的知識(shí)點(diǎn)也是java面試中最頻繁出現(xiàn)的點(diǎn),下面從源碼的角度來分析下Arraylist!
1,ArrayList中的屬性:ArrayList中的屬性主要定義了一個(gè)對(duì)象數(shù)組(Object[]),大小(size),初始容量(DEFAULT_CAPACITY=10)等等,從屬性中就可以知道ArrayList的底層就是一個(gè)數(shù)組,使用泛型E來存放構(gòu)造器中傳入的對(duì)象類型,當(dāng)然ArrayList存放的并不是對(duì)象本身,而是對(duì)象的引用,所以ArrayList不能存放八個(gè)基本類型的數(shù)據(jù);
2,ArrayList的主要方法:從下面截圖可以看出,ArrayList中的主要方法就是元素的add(增),remove(刪),set(改),get(查),而由這四大類方法自然衍生了獲取大小,擴(kuò)容,清空,包含等方法!
下面就主要方法進(jìn)行分析:
1,add方法(add(i),addAll()等類似):
①,先判斷加入元素后的數(shù)組大小,如果是小于初始容量則返回初始容量,否則返回+1后的容量值; ②,容量加1,同時(shí)跟未加入元素時(shí)的數(shù)組length比較,如果大于length,則使用grow方法進(jìn)行擴(kuò)容;
③, int newCapacity = oldCapacity + (oldCapacity >> 1); >>右移符號(hào),相當(dāng)于除二,即新容量為老容量的(1+0.5=1.5)倍,再進(jìn)行判斷是否新容量已經(jīng)超限(Integer.MAX_VALUE - 8),如果超限,則置為最大容量,否則使用Arrays.copyOf復(fù)制得到新數(shù)組;
2,remove方法(remove其他方法類似):
①,先判斷是否下標(biāo)越界,越界拋出異常,否則繼續(xù)
②,獲取到相應(yīng)下標(biāo)的元素;
③,將下標(biāo)后面的元素使用System.arraycopy往前移動(dòng)一位; ④,將遺留出的最后一位置為null,讓GC進(jìn)行回收,并返回②中獲得的值;
3,get,set方法:比較簡(jiǎn)單,就是使用指定下標(biāo)進(jìn)行數(shù)據(jù)替換或者獲取;
記錄幾個(gè)ArrayList中碰到的坑 :
1,線程不安全:所有的數(shù)據(jù)存取都是線程不安全的,所以多線程環(huán)境要么使用Vector,要么使用CopyOnWriteArrayList;
2,Arraylist是實(shí)現(xiàn)了序列化接口的,但使用subList方法返回的是SubList對(duì)象,這個(gè)對(duì)象并沒有序列化,在網(wǎng)絡(luò)傳輸中會(huì)報(bào)錯(cuò)的;
3,使用remove方法遇到的坑,因?yàn)閞emove方法重載了兩個(gè),remove(int i)和remove(Object o),如果是傳入Integer類型的參數(shù),默認(rèn)調(diào)用第二個(gè),則刪除元素失敗,案例如下:
可以說ArrayList是JAVA開發(fā)過程中最常使用的數(shù)據(jù)結(jié)構(gòu),底層實(shí)現(xiàn)也不難,但是如果不了解的話,面試容易被問倒,更多的JAVA技術(shù)會(huì)一直持續(xù)分享的,敬請(qǐng)關(guān)注。。。謝謝!