【问题标题】:Resize an Array while keeping current elements in Java?在保留 Java 中的当前元素的同时调整数组的大小?
【发布时间】:2025-12-19 11:25:09
【问题描述】:

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

我找到了像int[] newImage = new int[newWidth]; 这样的示例代码,但这会删除之前存储的元素。

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

【问题讨论】:

标签: java arrays


【解决方案1】:

您不能在 Java 中调整数组的大小。您需要:

  1. 创建一个所需大小的新数组,并将原始数组中的内容复制到新数组中,使用java.lang.System.arraycopy(...);

  2. 使用java.util.ArrayList<T> 类,当您需要使数组更大时,它会为您执行此操作。它很好地概括了您在问题中描述的内容。

  3. 使用java.util.Arrays.copyOf(...) 方法返回更大的数组,其中包含原始数组的内容。

【讨论】:

  • 好吧,我的数组列表属于“检查器”类类型,它存储不同的对象(int、string 等)。我创建了一个类型检查器的新对象,分配了一些值并将其添加到数组列表中。现在 eclipse 将进入调试模式,但不会在控制台中给出任何错误。你知道可能是什么问题吗?
  • 您应该将此作为一个单独的问题提出。
【解决方案2】:

不好,但可以:

    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

【讨论】:

  • @RyanMcCullagh ArrayLists 增加了复杂性以避免每次插入或删除都必须复制数组,这毫无价值。
【解决方案3】:

这里有几种方法。


方法一: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);

方法二:Arrays.copyOf()

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

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

注意这个方法通常使用System.arraycopy()behind the scenes


方法三:ArrayList

List 接口的 Resizable-array 实现。实现所有可选列表操作,并允许所有元素,包括 null。除了实现 List 接口之外,该类还提供了一些方法来操作内部用于存储列表的数组的大小。 (这个类大致相当于Vector,只是它是不同步的。)

ArrayList 的功能类似于数组,除了当您添加的元素超过它可以包含的内容时它会自动扩展。是backed by an arrayuses Arrays.copyOf

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      如果 Array 已满,建议创建 double size 的 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");
          }
      }
      

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          标准类 java.util.ArrayList 是可调整大小的数组,随着新元素的添加而增长。

          【讨论】:

            【解决方案8】:

            您无法调整数组的大小,但您可以重新定义它以保留旧值或使用 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();
                }
            }
            

            【讨论】:

              【解决方案9】:

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

              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);
              }
              

              【讨论】:

                【解决方案10】:

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

                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;
                           }
                       }
                    }    
                }
                

                【讨论】:

                  【解决方案11】:

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

                  所以我的建议是多思考找到一个解决方案,让您从流程开始就获得您需要的数组大小。这通常意味着您的代码需要更多时间(行)才能运行,但您会节省大量内存资源。

                  【讨论】:

                    最近更新 更多