java 实体类arraylist_如何实现Java的ArrayList经典实体类
arraylist是java集合框架中一個(gè)經(jīng)典的實(shí)現(xiàn)類(lèi)。他比起常用的數(shù)組而言,明顯的優(yōu)點(diǎn)在于,可以隨意的添加和刪除元素而不需考慮數(shù)組的大小。處于練手的目的,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的arraylist,并且把實(shí)現(xiàn)的過(guò)程在此記錄。
實(shí)現(xiàn)的arraylist主要的功能如下:
默認(rèn)構(gòu)造器和一個(gè)參數(shù)的有參構(gòu)造器
add方法
get方法
indexof方法
contains方法
size方法
isempty方法
remove方法
sort方法
這個(gè)簡(jiǎn)單的arraylist類(lèi) 取名為simplearraylist,全部的代碼查看simplearraylist代碼
構(gòu)造器
源碼arraylist一共有三個(gè)構(gòu)造器,一個(gè)無(wú)參構(gòu)造器,一個(gè)參數(shù)為int型有參構(gòu)造器,一個(gè)參數(shù)為collection型的有參構(gòu)造器。參數(shù)為collection型的構(gòu)造器用來(lái)實(shí)現(xiàn)將其他繼承collection類(lèi)的容器類(lèi)轉(zhuǎn)換成arraylist。simplearraylist類(lèi)因?yàn)檫€沒(méi)有手動(dòng)實(shí)現(xiàn)其他的容器類(lèi),所以實(shí)現(xiàn)的構(gòu)造方法只有2個(gè)。代碼如下:
public simplearraylist(){
this(default_capacity);
}
public simplearraylist(int size){
if (size < 0){
throw new illegalargumentexception("默認(rèn)的大小" + size);
}else{
elementdata = new object[size];
}
}
無(wú)參構(gòu)造器中的 default_capacity是定義的私有變量,默認(rèn)值是10,用來(lái)創(chuàng)建一個(gè)大小為10的數(shù)組。有參構(gòu)造器中,int參數(shù)是用來(lái)生成一個(gè)指定大小的object數(shù)組。將創(chuàng)建好的數(shù)組傳給elementdata。elementdata是真正的用來(lái)存儲(chǔ)元素的數(shù)組。
add方法
add 方法用來(lái)往容器中添加元素,add方法有兩個(gè)重載方法,一個(gè)是add(e e),另一個(gè)是add(int index, e e)。add本身很簡(jiǎn)單,但是要處理動(dòng)態(tài)數(shù)組,即數(shù)組大小不滿(mǎn)足的時(shí)候,擴(kuò)大數(shù)組的內(nèi)存。具體的代碼如下:
public void add(e e){
iscapacityenough(size + 1);
elementdata[size++] = e;
}
方法iscapacityenough就是來(lái)判斷是否需要擴(kuò)容,傳入的參數(shù)就是最小的擴(kuò)容空間。因?yàn)閍dd一個(gè)元素,所以最小的擴(kuò)容空間,即新的長(zhǎng)度是所有元素+ 1。這里的size就是真正的元素個(gè)數(shù)。
private void iscapacityenough(int size){
if (size > default_capacity){
explicitcapacity(size);
}
if (size < 0){
throw new outofmemoryerror();
}
}
判斷擴(kuò)容的方法也很簡(jiǎn)單,判斷需要擴(kuò)容的空間是不是比默認(rèn)的空間大。如果需要的空間比默認(rèn)的空間大,就調(diào)用explicitcapacity進(jìn)行擴(kuò)容。這里有個(gè)size小于0的判斷,出現(xiàn)size小于0主要是因?yàn)楫?dāng)size超過(guò)integer.max_value就會(huì)變成負(fù)數(shù)。
private final static int max_array_length = integer.max_value - 8;
private void explicitcapacity(int capacity){
int newlength = elementdata.length * 2;
if (newlength - capacity < 0){
newlength = capacity;
}
if (newlength > (max_array_length)){
newlength = (capacity > max_array_length ? integer.max_value : max_array_length);
}
elementdata = arrays.copyof(elementdata, newlength);
}
上面的代碼是擴(kuò)容的代碼,首先,定義一個(gè)數(shù)組最大的容量的常量為最大值,這個(gè)值按照官方的源碼中的解釋是要有些vm保留了數(shù)組的頭部信息在數(shù)組中,因此實(shí)際存放數(shù)據(jù)的大小就是整數(shù)的最大值 - 8
然后設(shè)定一個(gè)要擴(kuò)容的數(shù)組的大小,雖然上面說(shuō)了有一個(gè)擴(kuò)容空間的值 size + 1 ,這個(gè)是實(shí)際我們最小需要擴(kuò)容的大小。但為了繼續(xù)增加元素,而不頻繁的擴(kuò)容,因此一次性的申請(qǐng)多一些的擴(kuò)容空間。這里newlength 打算申請(qǐng)為 數(shù)組長(zhǎng)度的2倍,然后去判斷這個(gè)長(zhǎng)度是否滿(mǎn)足需要的擴(kuò)容空間的值。 即有了后續(xù)的兩段代碼
if (newlength - capacity < 0){
newlength = capacity;
}
if (newlength > (max_array_length)){
newlength = (capacity > max_array_length ? integer.max_value : max_array_length);
}
如果2倍的長(zhǎng)度仍然不滿(mǎn)足,則申請(qǐng)到需要的擴(kuò)容長(zhǎng)度。在我們只增加一個(gè)元素的情況下,這個(gè)判斷是永遠(yuǎn)不會(huì)生效的,但是如果有addall方法,則增加的元素很多,就要導(dǎo)致一次申請(qǐng)2倍的長(zhǎng)度是不夠的。第二個(gè)判斷是判斷newlength的長(zhǎng)度如果超過(guò)上面定義的數(shù)組最大長(zhǎng)度則判斷要需要的擴(kuò)容空間是否大于數(shù)組最大長(zhǎng)度,如果大于則newlength為 max_value ,否則為 max_array_length。
最后,真正實(shí)現(xiàn)數(shù)組擴(kuò)容到設(shè)定長(zhǎng)度的方法就沒(méi)意思了,調(diào)用arrays.copyof(elementdata, newlength)得到一個(gè)擴(kuò)容后的數(shù)組。
add的另一個(gè)重載方法也很簡(jiǎn)單。
public void add(int index, e e) {
//判斷是不是越界
checkrangeforadd(index);
//判斷需不需要擴(kuò)容
iscapacityenough(size + 1);
//將index的元素及以后的元素向后移一位
system.arraycopy(elementdata,index,elementdata,index + 1,size - index);
//將index下標(biāo)的值設(shè)為e
elementdata[index] = e;
size++;
}
private void checkrangeforadd(int index){
//這里index = size是被允許的,即支持頭,中間,尾部插入
if (index < 0 || index > size){
throw new indexoutofboundsexception("指定的index超過(guò)界限");
}
}
至此,一個(gè)簡(jiǎn)單的add方法就實(shí)現(xiàn)完了。
get方法
get方法用來(lái)得到容器中指定下標(biāo)的元素。方法實(shí)現(xiàn)比較簡(jiǎn)單,直接返回?cái)?shù)組中指定下標(biāo)的元素即可。
private void checkrange(int index) {
if (index >= size || index < 0){
throw new indexoutofboundsexception("指定的index超過(guò)界限");
}
}
public e get(int index){
checkrange(index);
return (e)elementdata[index];
}
indexof方法
indexof方法用來(lái)得到指定元素的下標(biāo)。實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單,需要判斷傳入的元素,代碼如下:
public int indexof(object o){
if (o != null) {
for (int i = 0 ; i < size ; i++){
if (elementdata[i].equals(0)){
return i;
}
}
}else {
for (int i = 0 ; i < size ; i++){
if (elementdata[i] == null) {
return i;
}
}
}
return -1;
}
判斷傳入的元素是否為null,如果為null,則依次與null。如果不為空,則用equals依次比較。匹配成功就返回下標(biāo),匹配失敗就返回-1。
contains方法
contains用來(lái)判斷該容器中是否包含指定的元素。在有了indexof方法的基礎(chǔ)上,contains的實(shí)現(xiàn)就很簡(jiǎn)單了。
public boolean contains(object o){
return indexof(o) >= 0;
}
size方法
size方法用來(lái)得到容器類(lèi)的元素個(gè)數(shù),實(shí)現(xiàn)很簡(jiǎn)單,直接返回size的大小即可。
public int size(){
return size;
}
isempty方法
isempty方法用來(lái)判斷容器是否為空,判斷size方法的返回值是否為0即可。
public boolean isempty(){
return size() == 0;
}
remove方法
remove方法是用來(lái)對(duì)容器類(lèi)的元素進(jìn)行刪除,與add一樣,remove方法也有兩個(gè)重載方法,分別是
remove(object o)和remove(int index)
public e remove(int index) {
e value = get(index);
int movesize = size - index - 1;
if (movesize > 0){
system.arraycopy(elementdata,index + 1, elementdata,index,size - index - 1);
}
elementdata[--size] = null;
return value;
}
public boolean remove(object o){
if (contains(o)){
remove(indexof(o));
return true;
}else {
return false;
}
}
第一個(gè)remove方法是核心方法,首先得到要?jiǎng)h除的下標(biāo)元素的值,然后判斷index后面的要前移的元素的個(gè)數(shù),如果個(gè)數(shù)大于零,則調(diào)用庫(kù)方法,將index后面的元素向前移一位。最后elementdata[--size] = null;縮減size大小,并將原最后一位置空。
第二個(gè)remove方法不需要向第一個(gè)方法一樣,需要告訴使用者要?jiǎng)h除的下標(biāo)對(duì)應(yīng)的元素,只需要判斷是否刪除成功即可。如果要?jiǎng)h除的元素在列表中,則刪除成功,如果不在則失敗。因此調(diào)用contains方法就可以判斷是否要?jiǎng)h除的元素在列表中。在則調(diào)用remove(int index),不在則返回失敗。
總結(jié)
自此,一個(gè)簡(jiǎn)單的arraylist就實(shí)現(xiàn)完了,實(shí)現(xiàn)的目的是為了弄清arraylist動(dòng)態(tài)數(shù)組的原理以及add與remove方法的內(nèi)容實(shí)現(xiàn)。同時(shí),也清楚了arraylist最大的擴(kuò)容空間就是integer的最大值。該類(lèi)的所有代碼在simplearraylist代碼
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持萬(wàn)仟網(wǎng)!
希望與廣大網(wǎng)友互動(dòng)??
點(diǎn)此進(jìn)行留言吧!
總結(jié)
以上是生活随笔為你收集整理的java 实体类arraylist_如何实现Java的ArrayList经典实体类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java socket 连接异常_jav
- 下一篇: java 微信转账 ca_error_C