javaArraylist源碼
『壹』 java ArrayList add() 方法報錯
直接看API就好,注意最後一句:IndexOutOfBoundsException - 如果索引超出范圍 (index < 0 || index > size())
add
public void add(int index,
E element)將指定的元素插入此列表中的指定位置。向右移動當前位於該位置的元素(如果有)以及所有後續元素(將其索引加 1)。
指定者:
介面 List<E> 中的 add
覆蓋:
類 AbstractList<E> 中的 add
參數:
index - 指定元素所插入位置的索引
element - 要插入的元素
拋出:
IndexOutOfBoundsException - 如果索引超出范圍 (index < 0 || index > size())
補充------------------------
在指定位置上插入並不是順序插入的意思呀
比如 1 2 3 4 5 6
現在有6個數,我可以在第三個位置插入一個數7,這樣就變成:1 2 7 3 4 5 6
但是我不能在第100個上位置插入,因為目前沒有那個位置,你不可能在那插入。
假設可以這樣插入的話,在100這個位置插入後,就要將容量擴充至至少100,雖然中間都是null,但是內存也要分配。同樣的你還得提防著是不是有人要在10萬、100萬這個位置插入數字呢?這樣說的話,內存遲早要爆掉了……
所以只能在已經被分配了的位置上插入數據,而不能人工的去先插入再要求分配內存空間。
『貳』 在java源碼中ArrayList數據增長是50%+1,為什麼其他人都說是50%
int newCapacity = (oldCapacity * 3)/2 + 1;
list初始化默認為10
當第第10個被賦值時list是不會增長長度的,因為此時不需要開辟新的內存
當第11個時將執行會新開辟內存 (if (minCapacity > oldCapacity) 為真 )
因為包含第11個,所以新增後數組長度則為 10 + 10/2 + 1
但是實際上未賦值的為5
也就是說每次開辟新內存時 都需要多開辟1為當前賦值用
所以出現了樓主所說的 //這里明顯是50%+1啊!
『叄』 如何自己實現一個簡單的ArrayList
ArrayList是Java集合框架中一個經典的實現類。他比起常用的數組而言,明顯的優點在於,可以隨意的添加和刪除元素而不需考慮數組的大小。
實現一個簡單的ArrayList,實現的過程:
實現的ArrayList主要的功能如下:
默認構造器和一個參數的有參構造器
add方法
get方法
indexOf方法
contains方法
size方法
isEmpty方法
remove方法
- public SimpleArrayList(){ this(DEFAULT_CAPACITY);
- } public SimpleArrayList(int size){ if (size < 0){ throw new IllegalArgumentException("默認的大小" + size);
- }else{
- elementData = new Object[size];
- }
- }
- public void add(E e){
- isCapacityEnough(size + 1);
- elementData[size++] = e;
- }
- private void isCapacityEnough(int size){ if (size > DEFAULT_CAPACITY){
- explicitCapacity(size);
- } if (size < 0){ throw new OutOfMemoryError();
- }
- }
- 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.Of(elementData, newLength);
- }
- if (newLength - capacity < 0){ newLength = capacity;
- } if (newLength > (MAX_ARRAY_LENGTH)){ newLength = (capacity > MAX_ARRAY_LENGTH ? Integer.MAX_VALUE : MAX_ARRAY_LENGTH);
- }
- public void add(int index, E e) {
- //判斷是不是越界
- checkRangeForAdd(index);
- //判斷需不需要擴容
- isCapacityEnough(size + 1);
- //將index的元素及以後的元素向後移一位
- System.array(elementData,index,elementData,index + 1,size - index);
- //將index下標的值設為e
- elementData[index] = e; size++;
- }
- private void checkRangeForAdd(int index){ //這里index = size是被允許的,即支持頭,中間,尾部插入
- if (index < 0 || index > size){ throw new IndexOutOfBoundsException("指定的index超過界限");
- }
- }
- private void checkRange(int index) { if (index >= size || index < 0){
- throw new IndexOutOfBoundsException("指定的index超過界限");
- }
- } public E get(int index){
- checkRange(index); return (E)elementData[index];
- }
- public int indexOf(Object o){ if (o != null) { for (int i = 0 ; i < size ; i++){ if (elementData[i].equals(o)){ return i;
- }
- }
- }else { for (int i = 0 ; i < size ; i++){ if (elementData[i] == null) { return i;
- }
- }
- } return -1;
- }
- public boolean contains(Object o){ return indexOf(o) >= 0;
- }
- public int size(){ return size;
- }
- public boolean isEmpty(){ return size() == 0;
- }
- public E remove(int index) {
- E value = get(index); int moveSize = size - index - 1; if (moveSize > 0){
- System.array(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;
- }
- }
這個簡單的ArrayList類 取名為SimpleArrayList,全部的代碼查看SimpleArrayList代碼
構造器
源碼ArrayList一共有三個構造器,一個無參構造器,一個參數為int型有參構造器,一個參數為Collection型的有參構造器。參數為Collection型的構造器用來實現將其他繼承Collection類的容器類轉換成ArrayList。SimpleArrayList類因為還沒有手動實現其他的容器類,所以實現的構造方法只有2個。代碼如下:
無參構造器中的DEFAULT_CAPACITY是定義的私有變數,默認值是10,用來創建一個大小為10的數組。有參構造器中,int參數是用來生成一個指定大小的Object數組。將創建好的數組傳給elementData。elementData是真正的用來存儲元素的數組。
add方法
add 方法用來往容器中添加元素,add方法有兩個重載方法,一個是add(E e),另一個是add(int index, E e)。add本身很簡單,但是要處理動態數組,即數組大小不滿足的時候,擴大數組的內存。具體的代碼如下:
方法isCapacityEnough就是來判斷是否需要擴容,傳入的參數就是最小的擴容空間。因為add一個元素,所以最小的擴容空間,即新的長度是所有元素+ 1。這里的size就是真正的元素個數。
判斷擴容的方法也很簡單,判斷需要擴容的空間是不是比默認的空間大。如果需要的空間比默認的空間大,就調用explicitCapacity進行擴容。這里有個size小於0的判斷,出現size小於0主要是因為當size超過Integer.MAX_VALUE就會變成負數。
上面的代碼是擴容的代碼,首先,定義一個數組最大的容量的常量為最大值,這個值按照官方的源碼中的解釋是要有些VM保留了數組的頭部信息在數組中,因此實際存放數據的大小就是整數的最大值 - 8
然後設定一個要擴容的數組的大小,雖然上面說了有一個擴容空間的值 size + 1 ,這個是實際我們最小需要擴容的大小。但為了繼續增加元素,而不頻繁的擴容,因此一次性的申請多一些的擴容空間。這里newLength 打算申請為 數組長度的2倍,然後去判斷這個長度是否滿足需要的擴容空間的值。 即有了後續的兩段代碼
如果2倍的長度仍然不滿足,則申請到需要的擴容長度。在我們只增加一個元素的情況下,這個判斷是永遠不會生效的,但是如果有addAll方法,則增加的元素很多,就要導致一次申請2倍的長度是不夠的。第二個判斷是判斷newLength的長度如果超過上面定義的數組最大長度則判斷要需要的擴容空間是否大於數組最大長度,如果大於則newLength為 MAX_VALUE ,否則為 MAX_ARRAY_LENGTH。
最後,真正實現數組擴容到設定長度的方法就沒意思了,調用Arrays.Of(elementData, newLength)得到一個擴容後的數組。
add的另一個重載方法也很簡單。
至此,一個簡單的add方法就實現完了。
get方法
get方法用來得到容器中指定下標的元素。方法實現比較簡單,直接返回數組中指定下標的元素即可。
indexOf方法
indexOf方法用來得到指定元素的下標。實現起來比較簡單,需要判斷傳入的元素,代碼如下:
判斷傳入的元素是否為null,如果為null,則依次與null。如果不為空,則用equals依次比較。匹配成功就返回下標,匹配失敗就返回-1。
contains方法
contains用來判斷該容器中是否包含指定的元素。在有了indexOf方法的基礎上,contains的實現就很簡單了。
size方法
size方法用來得到容器類的元素個數,實現很簡單,直接返回size的大小即可。
isEmpty方法
isEmpty方法用來判斷容器是否為空,判斷size方法的返回值是否為0即可。
remove方法
remove方法是用來對容器類的元素進行刪除,與add一樣,remove方法也有兩個重載方法,分別是
remove(Object o)和remove(int index)
第一個remove方法是核心方法,首先得到要刪除的下標元素的值,然後判斷index後面的要前移的元素的個數,如果個數大於零,則調用庫方法,將index後面的元素向前移一位。最後elementData[--size] = null;縮減size大小,並將原最後一位置空。
第二個remove方法不需要向第一個方法一樣,需要告訴使用者要刪除的下標對應的元素,只需要判斷是否刪除成功即可。如果要刪除的元素在列表中,則刪除成功,如果不在則失敗。因此調用contains方法就可以判斷是否要刪除的元素在列表中。在則調用remove(int index),不在則返回失敗。
『肆』 java中ArrayList類中的size()方法
size()就是獲取到ArrayList中存儲的對象的個數,舉例:
List list = new ArrayList();
list.add("123");
list.add("123");
int c =list.size();
System.out.print(c);
上面輸出的結果:2;
備註:list每次add,之後size值會進行加1,也就是說list的對象數增加了一個。
『伍』 java Arraylist擴容為什麼是1.5倍+1
//ArrayList類的源碼:對內部數組擴容
publicvoidensureCapacity(intminCapacity){
modCount++;
intoldCapacity=elementData.length;
if(minCapacity>oldCapacity){
ObjectoldData[]=elementData;
intnewCapacity=(oldCapacity*3)/2+1;//計算新容量
if(newCapacity<minCapacity)newCapacity=minCapacity;
//,sothisisawin:
elementData=Arrays.Of(elementData,newCapacity);
}
}
『陸』 一開始學習java有必要看源代碼嗎諸如Arraylist,Linkedlist的這些源代碼
你好,看源碼是可以幫助你以後寫代碼的。如果你是剛開始學,就沒有必要看那些東西。但是你要是有能力的話,看看還是很有幫助的,你說的那幾個類,等你學習到了,最好還是看看,可以加深你對他們的理解。
『柒』 java中Arraylist是干什麼的怎麼用
java中的ArrayList就是傳說中的動態數組,用MSDN中的說法,就是Array的復雜版本。
它提供了如下一些好處:動態的增加和減少元素實現了ICollection和IList介面靈活的設置數組的大小 。
ArrayList 的用法:
ArrayList List = new ArrayList(); for( int
i=0;i<10;i++ ) //
給數組增加10個Int元素 List.Add(i); //..
程序做一些處理
List.RemoveAt(5);//
將第6個元素移除 for( int i=0;i<3;i++ ) //
再增加3個元素
List.Add(i+20); Int32[] values =
(Int32[])List.ToArray(typeof(Int32));//
返回ArrayList包含的數組 。
(7)javaArraylist源碼擴展閱讀:
Arraylist的定義:
List 介面的大小可變數組的實現,位於API文檔的java.util.ArrayList<E>。
實現了所有可選列表操作,並允許包括 null 在內的所有元素。
除了實現 List 介面外,此類還提供一些方法來操作內部用來存儲列表的數組的大小。(此類大致上等同於 Vector 類,除了此類是不同步的。)
size、isEmpty、get、set、iterator 和 listIterator 操作都以固定時間運行。
add 操作以分攤的固定時間 運行,也就是說,添加 n 個元素需要 O(n) 時間。
其他所有操作都以線性時間運行(大體上講)。
與用於 LinkedList 實現的常數因子相比,此實現的常數因子較低。
每個 ArrayList 實例都有一個容量。該容量是指用來存儲列表元素的數組的大小。
它總是至少等於列表的大小。隨著向 ArrayList 中不斷添加元素,其容量也自動增長。
並未指定增長策略的細節,因為這不只是添加元素會帶來分攤固定時間開銷那樣簡單
在添加大量元素前,應用程序可以使用
ensureCapacity 操作來增加 ArrayList
實例的容量。這可以減少遞增式再分配的數量。
注意,此實現不是同步的。如果多個線程同時訪問一個 ArrayList
實例,而其中至少一個線程從結構上修改了列表,那麼它必須 保持外部同步。
(結構上的修改是指任何添加或刪除一個或多個元素的操作,或者顯式調整底層數組的大小;僅僅設置元素的值不是結構上的修改。)
這一般通過對自然封裝該列表的對象進行同步操作來完成。
如果不存在這樣的對象,則應該使用 Collections.synchronizedList 方法將該列表「包裝」起來。這最好在創建時完成,以防止意外對列表進行不同步的訪問:
List list = Collections.synchronizedList(new ArrayList(...));
此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗的。
在創建迭代器之後,除非通過迭代器自身的
remove 方法從結構上對列表進行修改,否則在任何時間以任何方式對列表進行修改,迭代器都會拋出
。
因此,面對並發的修改,迭代器很快就會完全失敗,而不是冒著在將來某個不確定時間發生任意不確定行為的風險。
注意,迭代器的快速失敗行為無法得到保證。
因為一般來說,不可能對是否出現不同步並發修改做出任何硬性保證。快速失敗迭代器會盡最大努力拋出
。
因此,為提高這類迭代器的正確性而編寫一個依賴於此異常的程序是錯誤的做法:迭代器的快速失敗行為應該僅用於檢測
bug。
『捌』 Java ArrayList C語言實現 函數體
分配內存的地方,修改成這樣
array->data=(void**)malloc(sizeof(ArrayList)*array->size);
編譯通過
『玖』 JAVA關於ArrayList的代碼的寫法
import java.util.ArrayList;
public class TestMain {
public static void main(String[] args){
String[] inStrArr = new String[]{"Nisse","Oskar","Lena","Adam","Jens","Beata","Cecilia","Stina","Pelle"};
ArrayList<String> retArr = smallStrings(inStrArr,"Lennart");
for(String retStr : retArr){
System.out.println(retStr);
}
}
public static ArrayList<String> smallStrings(String[] inStrArr,String str){
ArrayList<String> retArr = new ArrayList<String>();
for(String inStr : inStrArr){
if(str.compareTo(inStr) > 0){
retArr.add(inStr);
}
}
return retArr;
}
}
『拾』 arraylist java源碼為什麼判斷o==null
因為null不能參與運算,一旦參與,會報Null Pointer(空指針)異常。
如下:
Student a = null;
a.name 就會報異常。
ArrayList一樣的道理,如果為null,遍歷的時候同樣報錯。