调整数组大小,同时将当前元素保留在Java中?

我已经寻找了一种在Java中调整数组大小的方法,但是我找不到在保留当前元素的同时调整数组大小的方法。

我发现例如int[] newImage = new int[newWidth];这样的代码,但这会删除之前存储的元素。

我的代码基本上会这样做:每添加一个新元素,该数组就会增加1。我认为可以通过动态编程来完成,但是我不确定如何实现。

Mihai Bujanca asked 2019-11-08T16:31:08Z
11个解决方案
91 votes

您无法在Java中调整数组的大小。 您需要:

  1. 创建一个所需大小的新数组,然后使用java.util.Arrays.copyOf(...)将内容从原始数组复制到新数组

  2. 使用java.util.Arrays.copyOf(...)类,当您需要使数组更大时,该类将为您执行此操作。 它很好地封装了您在问题中描述的内容。

  3. 使用java.util.Arrays.copyOf(...)方法可返回具有原始数组内容的更大数组。

Steve McLeod answered 2019-11-08T16:32:00Z
23 votes

不好,但是可以:

    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

jlordo answered 2019-11-08T16:32:35Z
18 votes

这有两种方法。


方法1:System.arraycopy()

从指定的源数组(从指定位置开始)复制数组到目标数组的指定位置。 数组组件的子序列从src引用的源数组复制到dest引用的目标数组。 复制的组件数等于length参数。 将源数组中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:ArrayList

复制指定的数组,截断或使用null填充(如果需要),以便副本具有指定的长度。 对于在原始数组和副本中均有效的所有索引,两个数组将包含相同的值。 对于副本中有效但原始索引无效的任何索引,副本将包含null。 当且仅当指定长度大于原始数组的长度时,此类索引才会存在。 所得数组与原始数组具有完全相同的类。

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

请注意,此方法通常在幕后使用ArrayList


方法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());
Anubian Noob answered 2019-11-08T16:34:14Z
5 votes

您可以仅使用ArrayList为您完成工作。

Kirill Rakhman answered 2019-11-08T16:34:43Z
2 votes

您可以使用ArrayList代替array。 这样就可以添加n个元素

 List<Integer> myVar = new ArrayList<Integer>();
Suranga answered 2019-11-08T16:35:10Z
2 votes

标准类java.util.ArrayList是可调整大小的数组,在添加新元素时会增大。

Alexei Kaigorodov answered 2019-11-08T16:35:38Z
1 votes

无法更改数组大小。但是您可以通过创建更大尺寸的数组将一个数组的元素复制到另一个数组中。

如果阵列已满,建议创建两倍大小的阵列,如果阵列已满一半,则建议将阵列减小一半

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");
    }
}
Ranjeet Kumar answered 2019-11-08T16:36:10Z
1 votes

您无法调整数组的大小,但是可以重新定义它以保留旧值或使用java.util.List

以下是两个解决方案,但是在运行下面的代码时遇到了性能差异

Java列表快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();
    }
}
Codemix answered 2019-11-08T16:36:54Z
0 votes

无法调整数组大小。 但是,可以通过将原始数组复制到新大小的数组并保留当前元素来更改数组的大小。 也可以通过删除元素并调整大小来减小数组的大小。

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;
           }
       }
    }    
}
Lee answered 2019-11-08T16:37:23Z
0 votes

您可以在某些类中尝试以下解决方案:

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);
}
sreenath reddy answered 2019-11-08T16:37:50Z
0 votes

抱歉,但是目前无法调整数组大小,而且可能永远也不会。

因此,我的建议是,想更多地寻找一种解决方案,使您能够从过程的开始就获得所需阵列的大小。 这通常意味着您的代码需要更多的时间(行)来运行,但是您将节省大量的内存资源。

Daniel De León answered 2019-11-08T16:38:25Z
translate from https://stackoverflow.com:/questions/13197702/resize-an-array-while-keeping-current-elements-in-java