最近看到有同事在使用for循环的时候首先会将数组或者字符串的长度赋值给一个变量;在网上查了一下说是这样可以节约资源的消耗,真实的情况又是如何?
1.数组.length
String[] s = {
"qw","as","a"};
for(int i=0; i<s.length; i++) {
System.out.println(s[i]);
}
结论:纯属性,直接读取该数组的_length
字段,遍历时频繁读取并不会消耗过多资源。
数组在java里是一种特殊类型,有别于普通的“类的实例”对象,java里数组不是类,所以也就没有对应的class文件,数组类型是由jvm从元素类型合成出来的;在jvm中获取数组的长度是用arraylength
这个专门的字节码指令的;
那你可能会问jvm中是如何获取数组的长度?
答案是在数组的对象头里有一个_length
字段,记录数组长度,arraylength的实现只需要去读_length
字段就可以了。
数组一旦定义,长度是不可以改变的
2.集合.size()
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));
}
结论:list数组不会过多的消耗资源
源码中定义了一个size
变量,数组在新增或者删除元素的时候会直接修改这个变量的值,每次调用size方法的时候是直接去取size变量的,不会去重新计算数组的大小,所以对于list数组来说不会过多的消耗资源。
//JDK 1.8
public class ArrayList {
transient Object[] elementData; //实际存储对象的数组
private int size; //size成员变量
public int size() {
return size; //直接返回size
}
ArrayList 底层也是Object[]数组实现的,那么为何不直接调用elementData.length,而仍然要定义一个size属性?原因是数组长度是不可变的,一旦定义初始长度,后续无法修改,只能重新定义一个新的数组,elementData根据构造函数的initialCapacity参数设置初始大小,只不过每个位置上的元素为空,因此数组的长度不能代表实际元素的个数,因此由size属性负责。
3.字符串.length()
String str = "asdf";
for(int i=0,len=str.length();i<len;i++) {
System.out.println(str.charAt(i));
}
**结论:**原理和数组一样,也是不影响
字符串的底层是Char[],length()也是返回这个数组的长度
public final class String {
private final char value[]; //底层实现也是一个数组
public int length() {
return value.length;
}
我们知道字符串是不可改变的,从上述源码我们也能推断出原因,因为value[]被final 修饰。与集合.size()相比,由于string中的value[]数组不可变,可以直接利用value.length作为返回值。
参考:
Java中for循环每次都通过list.size、str.length、length()获取数组或者字符串的长度是否消耗资源 感觉里面针对字符串说法是错误的。