簡體   English   中英

調整數組大小,同時將當前元素保留在 Java 中?

[英]Resize an Array while keeping current elements in Java?

我在 Java 中搜索了一種調整數組大小的方法,但我找不到在保持當前元素的同時調整數組大小的方法。

我發現例如代碼int[] newImage = new int[newWidth]; ,但這會刪除之前存儲的元素。

我的代碼基本上會這樣做:每當添加一個新元素時,數組就會擴大1 我認為這可以通過動態編程來完成,但我不確定如何實現它。

您不能在 Java 中調整數組的大小。 你需要:

  1. 創建一個所需大小的新數組,並使用java.lang.System.arraycopy(...);將原始數組中的內容復制到新數組中java.lang.System.arraycopy(...);

  2. 使用java.util.ArrayList<T>類,當您需要使數組更大時,它會為您執行此操作。 它很好地概括了您在問題中描述的內容。

  3. 使用java.util.Arrays.copyOf(...)方法返回一個更大的數組,以及原始數組的內容。

不好,但有效:

    int[] a = {1, 2, 3};
    // make a one bigger
    a = Arrays.copyOf(a, a.length + 1);
    for (int i : a)
        System.out.println(i);

如前所述,使用ArrayList

這里有幾種方法可以做到這一點。


方法 1: System.arraycopy()

從指定的源數組中復制一個數組,從指定位置開始,到目標數組的指定位置。 數組組件的子序列從 src 引用的源數組復制到 dest 引用的目標數組。 復制的組件數等於長度參數。 源數組中位置 srcPos 到 srcPos+length-1 處的組件分別復制到目標數組的位置 destPos 到 destPos+length-1。

Object[] originalArray = new Object[5];   
Object[] largerArray = new Object[10];
System.arraycopy(originalArray, 0, largerArray, 0, originalArray.length);

方法 2: Arrays.copyOf()

復制指定的數組,用空值截斷或填充(如有必要),使副本具有指定的長度。 對於在原始數組和副本中都有效的所有索引,這兩個數組將包含相同的值。 對於副本中有效但不是原始索引的任何索引,副本將包含空值。 當且僅當指定的長度大於原始數組的長度時,此類索引才會存在。 生成的數組與原始數組的類完全相同。

Object[] originalArray = new Object[5];   
Object[] largerArray = Arrays.copyOf(originalArray, 10);

請注意,此方法通常在幕后使用System.arraycopy()


方法 3: ArrayList

List 接口的可調整大小的數組實現。 實現所有可選的列表操作,並允許所有元素,包括 null。 除了實現 List 接口之外,該類還提供了操作內部用於存儲列表的數組大小的方法。 (這個類大致相當於 Vector,只是它是不同步的。)

ArrayList 的功能與數組類似,不同之處在於它會在您添加的元素超出其所能容納的數量時自動擴展。 由一個數組支持,並使用 Arrays.copyOf

ArrayList<Object> list = new ArrayList<>();

// This will add the element, resizing the ArrayList if necessary.
list.add(new Object());

您可以使用ArrayList來為您完成工作。

無法更改數組大小。 但是您可以通過創建更大尺寸的 Array 將一個數組的元素復制到另一個數組中。

如果 Array 已滿,建議創建雙倍大小的 Array,如果 Array 已滿,則建議將 Array 減半

public class ResizingArrayStack1 {
    private String[] s;
    private int size = 0;
    private int index = 0;

    public void ResizingArrayStack1(int size) {
        this.size = size;
        s = new String[size];
    }


    public void push(String element) {
        if (index == s.length) {
            resize(2 * s.length);
        }
        s[index] = element;
        index++;
    }

    private void resize(int capacity) {
        String[] copy = new String[capacity];
        for (int i = 0; i < s.length; i++) {
            copy[i] = s[i];
            s = copy;
        }
    }

    public static void main(String[] args) {
        ResizingArrayStack1 rs = new ResizingArrayStack1();
        rs.push("a");
        rs.push("b");
        rs.push("c");
        rs.push("d");
    }
}

您可以使用 ArrayList 而不是數組。 這樣你就可以添加 n 個元素

 List<Integer> myVar = new ArrayList<Integer>();

標准類 java.util.ArrayList 是可調整大小的數組,當添加新元素時會增長。

您不能調整數組的大小,但可以重新定義它以保留舊值或使用 java.util.List

以下是兩種解決方案,但可以捕捉運行以下代碼的性能差異

Java Lists 快 450 倍,但內存重 20 倍!

testAddByteToArray1 nanoAvg:970355051   memAvg:100000
testAddByteToList1  nanoAvg:1923106     memAvg:2026856
testAddByteToArray1 nanoAvg:919582271   memAvg:100000
testAddByteToList1  nanoAvg:1922660     memAvg:2026856
testAddByteToArray1 nanoAvg:917727475   memAvg:100000
testAddByteToList1  nanoAvg:1904896     memAvg:2026856
testAddByteToArray1 nanoAvg:918483397   memAvg:100000
testAddByteToList1  nanoAvg:1907243     memAvg:2026856
import java.util.ArrayList;
import java.util.List;

public class Test {

    public static byte[] byteArray = new byte[0];
    public static List<Byte> byteList = new ArrayList<>();
    public static List<Double> nanoAvg = new ArrayList<>();
    public static List<Double> memAvg = new ArrayList<>();

    public static void addByteToArray1() {
        // >>> SOLUTION ONE <<<
        byte[] a = new byte[byteArray.length + 1];
        System.arraycopy(byteArray, 0, a, 0, byteArray.length);
        byteArray = a;
        //byteArray = Arrays.copyOf(byteArray, byteArray.length + 1); // the same as System.arraycopy()
    }

    public static void addByteToList1() {
        // >>> SOLUTION TWO <<<
        byteList.add(new Byte((byte) 0));
    }

    public static void testAddByteToList1() throws InterruptedException {
        System.gc();
        long m1 = getMemory();
        long n1 = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            addByteToList1();
        }
        long n2 = System.nanoTime();
        System.gc();
        long m2 = getMemory();
        byteList = new ArrayList<>();
        nanoAvg.add(new Double(n2 - n1));
        memAvg.add(new Double(m2 - m1));
    }

    public static void testAddByteToArray1() throws InterruptedException {
        System.gc();
        long m1 = getMemory();
        long n1 = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            addByteToArray1();
        }
        long n2 = System.nanoTime();
        System.gc();
        long m2 = getMemory();
        byteArray = new byte[0];
        nanoAvg.add(new Double(n2 - n1));
        memAvg.add(new Double(m2 - m1));
    }

    public static void resetMem() {
        nanoAvg = new ArrayList<>();
        memAvg = new ArrayList<>();
    }

    public static Double getAvg(List<Double> dl) {
        double max = Collections.max(dl);
        double min = Collections.min(dl);
        double avg = 0;
        boolean found = false;
        for (Double aDouble : dl) {
            if (aDouble < max && aDouble > min) {
                if (avg == 0) {
                    avg = aDouble;
                } else {
                    avg = (avg + aDouble) / 2d;
                }
                found = true;
            }
        }
        if (!found) {
            return getPopularElement(dl);
        }
        return avg;
    }

    public static double getPopularElement(List<Double> a) {
        int count = 1, tempCount;
        double popular = a.get(0);
        double temp = 0;
        for (int i = 0; i < (a.size() - 1); i++) {
            temp = a.get(i);
            tempCount = 0;
            for (int j = 1; j < a.size(); j++) {
                if (temp == a.get(j))
                    tempCount++;
            }
            if (tempCount > count) {
                popular = temp;
                count = tempCount;
            }
        }
        return popular;
    }

    public static void testCompare() throws InterruptedException {
        for (int j = 0; j < 4; j++) {
            for (int i = 0; i < 20; i++) {
                testAddByteToArray1();
            }
            System.out.println("testAddByteToArray1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\tmemAvg:" + getAvg(memAvg).longValue());
            resetMem();
            for (int i = 0; i < 20; i++) {
                testAddByteToList1();
            }
            System.out.println("testAddByteToList1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\t\tmemAvg:" + getAvg(memAvg).longValue());
            resetMem();
        }
    }

    private static long getMemory() {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }

    public static void main(String[] args) throws InterruptedException {
        testCompare();
    }
}

您可以在某些課程中嘗試以下解決方案:

int[] a = {10, 20, 30, 40, 50, 61};

// private visibility - or change it as needed
private void resizeArray(int newLength) {
    a = Arrays.copyOf(a, a.length + newLength);
    System.out.println("New length: " + a.length);
}

無法調整數組大小。 但是,可以通過將原始數組復制到新大小的數組並保留當前元素來更改數組的大小。 也可以通過刪除元素並調整大小來減小數組的大小。

import java.util.Arrays 
public class ResizingArray {

    public static void main(String[] args) {

        String[] stringArray = new String[2] //A string array with 2 strings 
        stringArray[0] = "string1";
        stringArray[1] = "string2";

        // increase size and add string to array by copying to a temporary array
        String[] tempStringArray = Arrays.copyOf(stringArray, stringArray.length + 1);
        // Add in the new string 
        tempStringArray[2] = "string3";
        // Copy temp array to original array
        stringArray = tempStringArray;

       // decrease size by removing certain string from array (string1 for example)
       for(int i = 0; i < stringArray.length; i++) {
           if(stringArray[i] == string1) {
               stringArray[i] = stringArray[stringArray.length - 1];
               // This replaces the string to be removed with the last string in the array
               // When the array is resized by -1, The last string is removed 
               // Which is why we copied the last string to the position of the string we wanted to remove
               String[] tempStringArray2 = Arrays.copyOf(arrayString, arrayString.length - 1);
                // Set the original array to the new array
               stringArray = tempStringArray2;
           }
       }
    }    
}

抱歉,但此時無法調整數組大小,並且可能永遠不會。

所以我的建議是,多想一想,找到一個解決方案,讓你從過程的開始就得到你需要的數組的大小。 這通常會暗示您的代碼需要更多時間(行)來運行,但您將節省大量內存資源。

我們不能使用數組數據類型來做到這一點。 而是使用一個可增長的數組,即 Java 中的 arrayList。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM