Java中for循环每次都通过list.size、str.length、length()获取数组或者字符串的长度是否消耗资源

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

猜你喜欢

转载自blog.csdn.net/yaomingyang/article/details/81130587