10

我正在做一个项目,但我不能使用任何现有的 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 多个项目的文本文件,就会出现分配错误。

我怎样才能动态更新这个数组(从而重新发明轮子)?

谢谢!

4

8 回答 8

20

你可以这样做:

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

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

于 2013-02-12T16:34:13.910 回答
5

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

基本上,您需要检查 是否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;
}

继续。

于 2013-02-12T16:31:48.907 回答
3

你不能更好地动态增加数组大小,你复制到新的array. 使用System.arrayCopy它,它比将每个元素复制到新数组中更好。供参考 为什么 System.arraycopy 在 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;
}
于 2013-02-12T16:33:55.583 回答
3

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

于 2013-02-12T16:35:01.647 回答
0

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

可能会有所帮助

于 2013-02-12T16:33:51.733 回答
0

Visual Basic 有一个很好的功能:ReDim Preserve.

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

于 2013-02-12T16:34:28.907 回答
0

让我们举一个例子,当您有一个包含 1 个元素的数组,并且您想要扩展大小以动态容纳 100 万个元素时。

情况1:

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 中,您必须将数组的大小增加 log 2 100 万 - 1 倍,即 18.9(假设)。

于 2016-02-10T16:05:24.333 回答
0
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

于 2017-09-15T14:23:19.287 回答