【问题标题】:How can we dynamically allocate and grow an array我们如何动态分配和增长数组
【发布时间】:2013-01-28 00:47:31
【问题描述】:

我正在做一个项目,但我不能使用任何现有的 java 数据结构(即 ArraysList、树等)

我只能使用数组。因此,我需要用新的内存动态更新一个数组。

我正在读取文本文件,并为数组内存预分配 100:

   String [] wordList;
   int wordCount = 0;
   int occurrence = 1;
   int arraySize = 100;
   wordList = new String[arraySize];
   while ((strLine = br.readLine()) != null)   {
         // Store the content into an array
         Scanner s = new Scanner(strLine);
         while(s.hasNext()) {
           wordList[wordCount] = s.next();
           wordCount++;
         } 
   }

现在这适用于 100 个以下的列表项。 br.readline 是遍历文本文件每一行的缓冲阅读器。我有它然后将每个单词存储到列表中,然后增加我的索引(wordCount)。

但是,一旦我有一个包含 100 多个项目的文本文件,就会出现分配错误。

如何动态更新这个数组(从而重新发明轮子)?

谢谢!

【问题讨论】:

  • 我认为最快的解决方案是计算输入文件中的行数('nix 中的wc -l filename)并第一次将数组分配到正确的大小。所有这些复制都比倒带文件并读取两次要慢得多......
  • java dynamic array sizes? 的可能重复项

标签: java arrays word-count


【解决方案1】:

您分配一个新数组(例如,容量翻​​倍),并将所有元素移至其中。

基本上你需要检查wordCount是否即将击中wordList.size(),当它击中时,创建一个长度是前一个数组的两倍的新数组,并将所有元素复制到其中(创建一个辅助方法这样做),并将wordList 分配给您的新数组。

要复制内容,您可以使用System.arraycopy,但我不确定您的限制是否允许,因此您可以简单地一个一个复制元素:

public String[] createNewArray(String[] oldArray){
    String[] newArray = new String[oldArray.length * 2];
    for(int i = 0; i < oldArray.length; i++) {
        newArray[i] = oldArray[i];
    }

    return newArray;
}

继续。

【讨论】:

  • 或者你可以使用array = Arrays.copyOf(array, newLength)
  • 是的,我知道。就像我说的,这个建议是在他不能使用内置方法的情况下提出的......就像他不能使用 ArrayList 等一样。
【解决方案2】:

您必须手动创建一个更大的新数组并复制项目。

this 可能会有所帮助

【讨论】:

    【解决方案3】:

    你不能更好地动态增加数组大小,你复制到新的array。为此使用System.arrayCopy,它比将每个元素复制到新数组中要好。以供参考 Why is System.arraycopy native in Java?.

    private static Object resizeArray (Object oldArray, int newSize) {
       int oldSize = java.lang.reflect.Array.getLength(oldArray);
       Class elementType = oldArray.getClass().getComponentType();
       Object newArray = java.lang.reflect.Array.newInstance(
             elementType, newSize);
       int preserveLength = Math.min(oldSize, newSize);
       if (preserveLength > 0)
          System.arraycopy(oldArray, 0, newArray, 0, preserveLength);
       return newArray;
    }
    

    【讨论】:

    • 或者你可以使用array = Arrays.copyOf(array, newLength)
    • 当然......如果您认为“相同”的标准库方法的重新实现不好。
    • @BrianRoach 我希望你检查了库的实现,你是什么意思 bad implementation?你能具体点吗?
    • 正是如此。你重新发明了轮子(不必要的)并且使它需要明确的演员表。
    • 我并不是说它没有显示 OP 如何 工作的价值,只是正确的答案是使用标准库(并且可能会更改您的示例使用泛型)
    【解决方案4】:

    你可以这样做:

    String [] wordList;
    int wordCount = 0;
    int occurrence = 1;
    int arraySize = 100;
    int arrayGrowth = 50;
    wordList = new String[arraySize];
    while ((strLine = br.readLine()) != null)   {
         // Store the content into an array
         Scanner s = new Scanner(strLine);
         while(s.hasNext()) {
             if (wordList.length == wordCount) {
                  // expand list
                  wordList = Arrays.copyOf(wordList, wordList.length + arrayGrowth);
             }
             wordList[wordCount] = s.next();
             wordCount++;
         } 
    }
    

    使用java.util.Arrays.copyOf(String[]) 基本上是做同样的事情:

    if (wordList.length == wordCount) {
        String[] temp = new String[wordList.length + arrayGrowth];
        System.arraycopy(wordList, 0, temp, 0, wordList.length);
        wordList = temp;
    }
    

    除了它是一行代码而不是三行。 :)

    【讨论】:

      【解决方案5】:

      Visual Basic 有一个不错的功能:ReDim Preserve

      有人写了一个等效的函数 - 你可以找到它here。我认为它完全符合您的要求(而且您不是在重新发明轮子 - 您是在复制别人的)...

      【讨论】:

        【解决方案6】:

        看看Java ArrayList 的实现。 Java ArrayList 在内部使用固定大小的数组,一旦元素数量超过当前大小,就会重新分配数组。您也可以在类似的线路上实施。

        【讨论】:

        • 或者直接使用array = Arrays.copyOf(array, newLength)
        【解决方案7】:

        假设您有一个包含 1 个元素的数组,并且您希望扩展大小以动态容纳 100 万个元素。

        案例一:

        String [] wordList = new String[1];
        String [] tmp = new String[wordList.length + 1];
        for(int i = 0; i < wordList.length ; i++){
            tmp[i] = wordList[i];
        }
        wordList = tmp;
        

        案例 2(通过加法因子增加大小):

        String [] wordList = new String[1];
        String [] tmp = new String[wordList.length + 10];
        for(int i = 0; i < wordList.length ; i++){
            tmp[i] = wordList[i];
        }
        wordList = tmp;
        

        案例 3(通过乘数增加大小):

        String [] wordList = new String[1];
        String [] tmp = new String[wordList.length * 2];
        for(int i = 0; i < wordList.length ; i++){
            tmp[i] = wordList[i];
        }
        wordList = tmp;
        

        当动态扩展数组的大小时,使用 Array.copy 或迭代数组并使用 for 循环将元素复制到新数组,实际上是迭代数组的每个元素。这是一项昂贵的操作。 Array.copy 将是干净和优化的,但仍然很昂贵。所以,我建议将数组长度增加一个乘数。

        它有什么帮助,

        在情况 1 中,要容纳 100 万个元素,您必须将数组的大小增加 100 万 - 1 倍,即 999,999 倍。

        在情况 2 中,您必须将数组的大小增加 100 万 / 10 - 1 倍,即 99,999 倍。

        在情况 3 中,您必须将数组的大小增加 log2100 万 - 1 倍,即 18.9(假设)。

        【讨论】:

          【解决方案8】:
          public class Arr {
          
              public static void main(String[] args) {
                  // TODO Auto-generated method stub
                  int a[] = {1,2,3};
                  //let a[] is your original array
                  System.out.println(a[0] + " " + a[1] + " " + a[2]);
                  int b[];
                  //let b[] is your temporary array with size greater than a[]
                  //I have took 5
                  b = new int[5];
                  //now assign all a[] values to b[]
                  for(int i = 0 ; i < a.length ; i ++)
                      b[i] = a[i];
                  //add next index values to b
                  b[3] = 4;
                  b[4] = 5;
                  //now assign b[] to a[]
                  a = b;
                  //now you can heck that size of an original array increased
                  System.out.println(a[0] + " " + a[1] + " " + a[2] + " " + a[3] + " " 
              + a[4]);
              }
          
          }
          

          上述代码的输出是:

          1 2 3

          1 2 3 4 5

          【讨论】:

            猜你喜欢
            • 2021-03-27
            • 2013-08-13
            • 2014-01-01
            • 2023-02-10
            • 2015-06-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多