最近看到有同事在使用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循环过多消耗资源。