ArrayList就是傳說中的動態數組
認真閱讀本文
首先看到對ArrayList的定義
[java]
public class ArrayList<E> extends AbstractList<E> implements List<E>
從ArrayList<E>可以看出它是支持泛型的
AbstractList提供了List接口的默認實現(個別方法為抽象方法)
List接口定義了列表必須實現的方法
RandomAccess是一個標記接口
實現了Cloneable接口的類
通過實現 java
ArrayList的屬性
ArrayList定義只定義類兩個私有屬性
[java]
/**
* The array buffer into which the elements of the ArrayList are stored
* The capacity of the ArrayList is the length of this array buffer
*/
private transient Object[] elementData;
/**
* The size of the ArrayList (the number of elements it contains)
*
* @serial
*/
private int size;
[java]
很容易理解
有個關鍵字需要解釋
Java的serialization提供了一種持久化對象實例的機制
ansient是Java語言的關鍵字
有點抽象
[java]
public class UserInfo implements Serializable {
private static final long serialVersionUID =
private String name;
private transient String psw;
public UserInfo(String name
this
this
}
public String toString() {
return
}
}
public class TestTransient {
public static void main(String[] args) {
UserInfo userInfo = new UserInfo(
System
try {
// 序列化
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(
o
o
} catch (Exception e) {
// TODO: handle exception
e
}
try {
// 重新讀取內容
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
UserInfo readUserInfo = (UserInfo) in
//讀取後psw的內容為null
System
} catch (Exception e) {
// TODO: handle exception
e
}
}
}
被標記為transient的屬性在對象被序列化的時候不會被保存
接著回到ArrayList的分析中……
ArrayList的構造方法
看完屬性看構造方法
[java]
/**
* Constructs an empty list with the specified initial capacity
*/
public ArrayList(int initialCapacity) {
super()
if (initialCapacity <
throw new IllegalArgumentException(
initialCapacity)
this
}
/**
* Constructs an empty list with an initial capacity of ten
*/
public ArrayList() {
this(
}
/**
* Constructs a list containing the elements of the specified
* collection
* iterator
*/
public ArrayList(Collection<? extends E> c) {
elementData = c
size = elementData
// c
if (elementData
elementData = pyOf(elementData
}
第一個構造方法使用提供的initialCapacity來初始化elementData數組的大小
ArrayList的其他方法
add(E e)
add(E e)都知道是在尾部添加一個元素
[java]
public boolean add(E e) {
ensureCapacity(size +
elementData[size++] = e;
return true;
}
書上都說ArrayList是基於數組實現的
看到add(E e)中先調用了ensureCapacity(size+
根據ensureCapacity的方法名可以知道是確保容量用的
[java]
/**
* Increases the capacity of this <tt>ArrayList</tt> instance
* necessary
* specified by the minimum capacity argument
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity *
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size
elementData = pyOf(elementData
}
}
The number of times this list has been structurally modified
這是對modCount的解釋
增加modCount之後
所以調用ensureCapacity至少將elementData的容量增加的
容量的拓展將導致數組元素的復制
可以理解提前分配好空間可以提高運行速度
add(int index
add(int index
[java]
public void add(int index
if (index > size || index <
throw new IndexOutOfBoundsException(
ensureCapacity(size+
System
size
elementData[index] = element;
size++;
}
首先判斷指定位置index是否超出elementData的界限
addAll(Collection<? extends E> c)
[java]
public boolean addAll(Collection<? extends E> c) {
Object[] a = c
int numNew = a
ensureCapacity(size + numNew)
System
size += numNew;
return numNew !=
}
先將集合c轉換成數組
addAll(int index
[java]
public boolean addAll(int index
if (index > size || index <
throw new IndexOutOfBoundsException(
Object[] a = c
int numNew = a
ensureCapacity(size + numNew)
int numMoved = size
if (numMoved >
System
numMoved)
System
size += numNew;
return numNew !=
}
先判斷index是否越界
clear()
[java]
public void clear() {
modCount++;
// Let gc do its work
for (int i =
elementData[i] = null;
size =
}
clear的時候並沒有修改elementData的長度(好不容易申請
clone()
返回此 ArrayList 實例的淺表副本
[java]
public Object clone() {
try {
ArrayList<E> v = (ArrayList<E>) super
v
v
return v;
} catch (CloneNotSupportedException e) {
// this shouldn
throw new InternalError()
}
}
調用父類的clone方法返回一個對象的副本
contains(Object)
[html]
public boolean contains(Object o) {
return indexOf(o) >=
}
indexOf方法返回值與
indexOf(Object)
[java]
public int indexOf(Object o) {
if (o == null) {
for (int i =
if (elementData[i]==null)
return i;
} else {
for (int i =
if (o
return i;
}
return
}
通過遍歷elementData數組來判斷對象是否在list中
既然看了indexOf(Object)方法
[java]
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size
if (elementData[i]==null)
return i;
} else {
for (int i = size
if (o
return i;
}
return
}
采用了從後向前遍歷element數組
get(int index)
這個方法看著很簡單
[java]
public E get(int index) {
RangeCheck(index)
return (E) elementData[index];
}
但看代碼的時候看到調用了RangeCheck方法
[java]
/**
* Checks if the given index is in range
*/
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
}
就是檢查一下是不是超出數組界限了
isEmpty()
直接返回size是否等於
remove(int index)
[java]
public E remove(int index) {
RangeCheck(index)
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size
if (numMoved >
System
numMoved)
elementData[
return oldValue;
}
首先是檢查范圍
remove(Object o)
[java]
public boolean remove(Object o) {
if (o == null) {
for (int index =
if (elementData[index] == null) {
fastRemove(index)
return true;
}
} else {
for (int index =
if (o
fastRemove(index)
return true;
}
}
return false;
}
首先通過代碼可以看到
[java]
private void fastRemove(int index) {
modCount++;
int numMoved = size
if (numMoved >
System
numMoved)
elementData[
}
removeRange(int fromIndex
[java]
protected void removeRange(int fromIndex
modCount++;
int numMoved = size
System
numMoved)
// Let gc do its work
int newSize = size
while (size != newSize)
elementData[
}
執行過程是將elementData從toIndex位置開始的元素向前移動到fromIndex
這個方法是protected
這是一個解釋
先看下面這個例子
[java]
ArrayList<Integer> ints = new ArrayList<Integer>(Arrays
// fromIndex low endpoint (inclusive) of the subList
// toIndex high endpoint (exclusive) of the subList
ints
System
輸出結果是[
set(int index
[java]
public E set(int index
RangeCheck(index)
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
首先檢查范圍
size()
size()方法直接返回size
toArray()
[java]
public Object[] toArray() {
return pyOf(elementData
}
調用pyOf將返回一個數組
toArray(T[] a)
[java]
public <T> T[] toArray(T[] a) {
if (a
// Make a new array of a
return (T[]) pyOf(elementData
System
if (a
a[size] = null;
return a;
}
如果傳入數組的長度小於size
trimToSize()
[java]
public void trimToSize() {
modCount++;
int oldCapacity = elementData
if (size < oldCapacity) {
elementData = pyOf(elementData
}
}
由於elementData的長度會被拓展
學習Java最好的方式還必須是讀源碼
如果有大量的FGC就要查詢是否有內存洩漏的問題了
如果為了更好的證明FGC對服務器性能的影響
從上圖可以發現執行FGC的情況
上圖是jvm堆內存的使用情況
下面我們在看看大量full GC 對服務器性能的影響
從圖中可以發現有
當然通過上面幾種方法我們可以發現java的內存洩漏問題
首先我們必須對jvm的堆內存進行dump
MemoryAnalyzer的用戶我在這裡就不一一說明了
其中深藍色的部分就為內存洩漏的部分
從上圖我們可以發現紅線圈著的方法占用了堆內存的
本人剛剛完成了雲存儲架構師的培訓學習(包括了linux的內核了解
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26553.html