亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java數(shù)組擴(kuò)容的三大小結(jié)

 更新時(shí)間:2023年08月14日 10:19:13   作者:白.都  
當(dāng)數(shù)組需要容納更多元素時(shí),可以通過(guò)擴(kuò)容來(lái)增加其容量,本文主要介紹了Java數(shù)組擴(kuò)容的三大小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

方案1:新建數(shù)組

這種方法新建的數(shù)組必須要比原先的長(zhǎng)度要長(zhǎng),然后將原來(lái)的數(shù)組內(nèi)容移到新的數(shù)組中

<!--more-->
int[] a = {1, 2, 3, 4, 5};
?
// 創(chuàng)建新數(shù)組,長(zhǎng)度為源數(shù)組的兩倍
int[] b = new int[a.length * 2];
?
// 將舊數(shù)組內(nèi)容復(fù)制到新數(shù)組
for (int i = 0; i < a.length; i++) {
? ? b[i] = a[i];
}
?
// 新數(shù)組內(nèi)容賦值給源數(shù)組
a = b;
?
// 打印結(jié)果
System.out.println(Arrays.toString(a));

輸出結(jié)果

 [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]

方案2:Arrays.copyOf

int[] a = {1, 2, 3, 4, 5};
?
// 第一個(gè)參數(shù)是拷貝的數(shù)組,第二個(gè)參數(shù)是擴(kuò)容長(zhǎng)度,且返回一個(gè)新數(shù)組
a = Arrays.copyOf(a, a.length * 2);
?
// 打印結(jié)果
System.out.println(Arrays.toString(a));

輸出結(jié)果

 [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]

Arrays.copyof是用于數(shù)組進(jìn)行復(fù)制時(shí)常使用的方法,本身在Arrays類(lèi)里面,而之所以能這么使用而不用創(chuàng)建對(duì)象在于該方法本身由static修飾,被static修飾的方法可以在該類(lèi)創(chuàng)建對(duì)象前載入jvm。

public static long[] copyOf(long[] original, int newLength) {
    long[] copy = new long[newLength];
    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
    return copy;
}

通過(guò)上面的代碼可以看出,其本質(zhì)是調(diào)用了System.arraycopy方法。

先產(chǎn)生一個(gè)新的數(shù)組然后調(diào)用arraycopy方法最后在返回產(chǎn)生的新數(shù)組。但是我們進(jìn)行數(shù)組擴(kuò)容的時(shí)候禪城了新數(shù)組,但是原數(shù)組依然存在,造成了內(nèi)存的浪費(fèi)。

方案3:System.arraycopy

int[] a = {1, 2, 3, 4, 5};
?
// 定義新數(shù)組,長(zhǎng)度為源數(shù)組的兩倍
int[] b = new int[a.length * 2];
?
/**
 * src      需要拷貝的源數(shù)組
 * srcPos   源數(shù)組中的起始位置
 * dest     目標(biāo)數(shù)組
 * destPos  目標(biāo)數(shù)組中的起始位置
 * length   要復(fù)制的數(shù)組元素?cái)?shù)量
 */
System.arraycopy(a, 0, b, 0, a.length);
?
// 新數(shù)組內(nèi)容賦值給原數(shù)組
a = b;
?
// 打印結(jié)果
System.out.println(Arrays.toString(a));

輸出結(jié)果

 [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]

arraycopy源碼

/**
     * @param src     the source array.  源數(shù)組
     * @param srcPos  starting position in the source array. 要復(fù)制的源數(shù)組的起始位置
     * @param dest    the destination array. 目標(biāo)數(shù)組
     * @param destPos starting position in the destination data. 目標(biāo)數(shù)組的起始位置
     * @param length  the number of array elements to be copied. 要復(fù)制的長(zhǎng)度
     * @throws IndexOutOfBoundsException if copying would cause
     *                                   access of data outside array bounds.
     *                                   如果復(fù)制會(huì)導(dǎo)致數(shù)據(jù)的訪問(wèn)超出數(shù)組邊界。
     *                                   則會(huì)報(bào)IndexOutOfBoundsException索引越界異常
     * @throws ArrayStoreException       if an element in the <code>src</code> array
     *                                   could not be stored into the 
                                         <code>dest</code> array
     *                                   because of a type mismatch.
     *                                   如果由于類(lèi)型不匹配而無(wú)法將src數(shù)組中的元素存儲(chǔ)到dest數(shù)組中。
     *                                   則會(huì)報(bào) ArrayStoreException數(shù)組存儲(chǔ)異常
     * @throws NullPointerException      if either <code>src</code> or
     *                                   <code>dest</code> is <code>null</code>.
     *                                   如果src或dest為null。
     *                                   則會(huì)報(bào)NullPointerException空指針異常
     */
?
    public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

System.arraycopy()的幾種常用方法(普通for循環(huán)和arraycopy方法對(duì)比)

1. 從舊數(shù)組拷貝到新數(shù)組

//從舊數(shù)組拷貝到新數(shù)組
for (int i=0;i<size;i++){
    arrayNew[i]=array[i];
}
System.arraycopy(array, 0, arrayNew, 0, array.length);

2. 從左向右循環(huán),逐個(gè)元素向左挪一位。

//從左向右循環(huán),逐個(gè)元素向左挪一位。
for (int i = index; i < size - 1; i++) {
    array[i] = array[i + 1];
}
System.arraycopy(array, index + 1, array, index, size - 1 - index);

3. 從右向左循環(huán),逐個(gè)元素向右挪一位。

//從右向左循環(huán),逐個(gè)元素向右挪一位。
for (int i = size - 1; i >= index; i--) {
    array[i + 1] = array[i];
}
System.arraycopy(array, index, array, index + 1, size - index);

System.arraycopy()深層理解

深復(fù)制還是淺復(fù)制

先說(shuō)結(jié)論 :

  • 當(dāng)數(shù)組為一維數(shù)組,且元素為基本類(lèi)型或String類(lèi)型時(shí),屬于深拷貝,即原數(shù)組與新數(shù)組的元素不會(huì)相互影響。
  • 當(dāng)數(shù)組為多維數(shù)組,或一維數(shù)組中的元素為引用類(lèi)型時(shí),屬于淺拷貝,原數(shù)組與新數(shù)組的元素引用指向同一個(gè)對(duì)象。

引用對(duì)象

構(gòu)建一個(gè)User類(lèi)型源數(shù)組,復(fù)制后至target數(shù)組,比較第一個(gè)元素的內(nèi)存地址,判斷結(jié)果是相同的,證明為淺復(fù)制;后修改target數(shù)組數(shù)組的隨機(jī)元素,發(fā)現(xiàn)原來(lái)的值也變了。

public class SystemArrayCopyTestCase {
?
    public static void main(String[] args) {
        User[] users = new User[] { 
                new User(1), 
                new User(2),
                new User(3) };// 初始化對(duì)象數(shù)組
        User[] target = new User[users.length];// 新建一個(gè)目標(biāo)對(duì)象數(shù)組
        System.arraycopy(users, 0, target, 0, users.length);// 實(shí)現(xiàn)復(fù)制
        System.out.println("源對(duì)象與目標(biāo)對(duì)象的物理地址是否一樣:" + (users[0] == target[0] ? "淺復(fù)制" : "深復(fù)制"));  //淺復(fù)制
        target[0].setId(5);
        System.out.println("修改目標(biāo)對(duì)象的屬性值后源對(duì)象users:");
        for (User user : users) {
            System.out.println(user);
        }
    }
}
?
class User {
}
?

System.arraycopy() 在拷貝數(shù)組的時(shí)候,采用的使用潛復(fù)制,復(fù)制結(jié)果是一維的引用變量傳遞給新數(shù)組的一維數(shù)組,修改新數(shù)組時(shí),會(huì)影響原來(lái)的數(shù)組。

一維數(shù)組和多維數(shù)組

將一維數(shù)組作源數(shù)組,進(jìn)行拷貝,產(chǎn)生target數(shù)組;然后修改target數(shù)組中的元素,新數(shù)組沒(méi)變,證明是值拷貝,修改新數(shù)組不會(huì)影響原來(lái)的值。

將多維數(shù)組作源數(shù)組,進(jìn)行拷貝至目標(biāo)數(shù)組,修改至目標(biāo)數(shù)組的元素,新數(shù)組也變了,說(shuō)明是二者是相同的引用,而這時(shí)改變其中任何一個(gè)數(shù)組的元素的值,其實(shí)都修改了共同數(shù)組元素的值,所以原數(shù)組和新數(shù)組的元素值都一樣了

線程是否安全(摘自網(wǎng)絡(luò))

System.ayyaycopy是不安全的。

public class ArrayCopyThreadSafe {
    private static int[] arrayOriginal = new int[1024 * 1024 * 10];
    private static int[] arraySrc = new int[1024 * 1024 * 10];
    private static int[] arrayDist = new int[1024 * 1024 * 10];
    private static ReentrantLock lock = new ReentrantLock();
?
    private static void modify() {
        for (int i = 0; i < arraySrc.length; i++) {
            arraySrc[i] = i + 1;
        }
    }
?
    private static void copy() {
        System.arraycopy(arraySrc, 0, arrayDist, 0, arraySrc.length);
    }
?
    private static void init() {
        for (int i = 0; i < arraySrc.length; i++) {
            arrayOriginal[i] = i;
            arraySrc[i] = i;
            arrayDist[i] = 0;
        }
    }
?
    private static void doThreadSafeCheck() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println("run count: " + (i + 1));
            init();
            Condition condition = lock.newCondition();
?
            new Thread(new Runnable() {
                @Override
                public void run() {
                    lock.lock();
                    condition.signalAll();
                    lock.unlock();
                    copy();
                }
            }).start();
?
?
            lock.lock();
            // 這里使用 Condition 來(lái)保證拷貝線程先已經(jīng)運(yùn)行了.
            condition.await();
            lock.unlock();
?
            Thread.sleep(2); // 休眠2毫秒, 確??截惒僮饕呀?jīng)執(zhí)行了, 才執(zhí)行修改操作.
            modify();
?
            if (!Arrays.equals(arrayOriginal, arrayDist)) {
                throw new RuntimeException("System.arraycopy is not thread safe");
            }
        }
    }
?
    public static void main(String[] args) throws Exception {
        doThreadSafeCheck();
    }
}
?

這個(gè)例子的具體操作是:

arrayOriginal 和 arraySrc 初始化時(shí)是相同的, 而 arrayDist 是全為零的.

啟動(dòng)一個(gè)線程運(yùn)行 copy() 方法來(lái)拷貝 arraySrc 到 arrayDist 中.

在主線程執(zhí)行 modify() 操作, 修改 arraySrc 的內(nèi)容. 為了確保 copy() 操作先于 modify() 操作, 我使用 Condition, 并且延時(shí)了兩毫秒, 以此來(lái)保證執(zhí)行拷貝操作(即System.arraycopy) 先于修改操作.

根據(jù)第三點(diǎn), 如果 System.arraycopy 是線程安全的, 那么先執(zhí)行拷貝操作, 再執(zhí)行修改操作時(shí), 不會(huì)影響復(fù)制結(jié)果, 因此 arrayOriginal 必然等于 arrayDist; 而如果 System.arraycopy 是線程不安全的, 那么 arrayOriginal 不等于 arrayDist.

run count: 1
Exception in thread "main" java.lang.RuntimeException: System.arraycopy is not thread safe
    at ArrayCopyThreadSafe.doThreadSafeCheck(ArrayCopyThreadSafe.java:54)
    at ArrayCopyThreadSafe.main(ArrayCopyThreadSafe.java:60)

結(jié)論 :System.ayyaycopy是不安全的。

System.arraycopy()和for()相比誰(shuí)更高效

當(dāng)測(cè)試數(shù)組的范圍比較小的時(shí)候,兩者相差的時(shí)間無(wú)幾,當(dāng)測(cè)試數(shù)組的長(zhǎng)度達(dá)到百萬(wàn)級(jí)別,System.arraycopy的速度優(yōu)勢(shì)就開(kāi)始體現(xiàn)了,根據(jù)對(duì)底層的理解,System.arraycopy是對(duì)內(nèi)存直接進(jìn)行復(fù)制,減少了for循環(huán)過(guò)程中的尋址時(shí)間,從而提高了效能。

到此這篇關(guān)于Java數(shù)組擴(kuò)容的三大小結(jié)的文章就介紹到這了,更多相關(guān)Java數(shù)組擴(kuò)容內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論