最近看到有同事在使用for循環的時候首先會將數組或者字符串的長度賦值給一個變量;在網上查了一下說是這樣可以節約資源的消耗,真實的情況又是如何?讓我們看下他們的源碼來分析。
1.將數組的長度賦值給變量len
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
for(int i=0,len=list.size();i<len;i++) {
System.out.println(list.get(i));
}
將數組的長度賦值給len變量,這樣不用每次循環都去調用size()方法;這樣能不能節約資源那我們就看下源碼是如何定義的:
private int size;
...
public int size() {
return size;
}
//數組中新增元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//數組中刪除元素
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
我們可以看到源碼中定義了一個size變量,數組在新增或者刪除元素的時候會直接修改這個變量的值,每次調用size方法的時候是直接去取size變量的,不會去重新計算數組的大小,所以對於list數組來說不會過多的消耗資源。
2.字符串類型的長度賦值給變量len
String str = "asdf";
for(int i=0,len=str.length();i<len;i++) {
System.out.println(str.charAt(i));
}
字符串的長度是要調用length方法獲取,我們看下源碼是如何操作的:
/** The value is used for character storage. */
private final char value[];
...
/**
* Returns the length of this string.
* The length is equal to the number of <a href="Character.html#unicode">Unicode
* code units</a> in the string.
*
* @return the length of the sequence of characters represented by this
* object.
*/
public int length() {
return value.length;
}
我們可以看到字符串的底層是存儲在一個char類型的數組中的,獲取字符串的長度每次都需要計算value數組中字符的個數,也就是數組的長度,循環每次都會計算,這樣就會消耗額外的資源,所以建議字符串類型的定義一個變量存儲字符串的長度。
3.數組類型計算長度length屬性
首先數組是一個對象類型,數組一旦創建成功它的長度就固定了,所以它可以定義一個變量類型length屬性來存儲數組的長度,也就是說每次調用lengh屬性的時候不會重新的計算數組的長度,也就不會過多的消耗資源;
數組在java裏是一種特殊類型,有別於普通的“類的實例”對象,java裏數組不是類,所以也就沒有對應的class文件,數組類型是由jvm從元素類型合成出來的;在jvm中獲取數組的長度是用arraylength這個專門的字節碼指令的;
那你可能會問jvm中是如何獲取數組的長度?
答案是在數組的對象頭裏有一個_length字段,記錄數組長度,arraylength的實現只需要去讀_length字段就可以了。
String[] s = {"qw","as","a"};
for(int i=0; i<s.length; i++) {
System.out.println(s[i]);
}
當我們對數組的length進行++操作的時候編譯器會報The final field array.length cannot be assigned,說明這個變量是一個final類型的,不可以修改。
總結:根據上面的幾種種情況,數組和List集合不會過多消耗資源,字符串長度for循環是會消耗多餘資源,所以建議定義一個變量存儲數組或者字符串長度,養成良好的習慣,這樣可以避免不是很瞭解底層的實現方式的數組等for循環過多消耗資源。