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循環過多消耗資源。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章