【问题标题】:Increasing array length dynamically while adding objects to array在将对象添加到数组时动态增加数组长度
【发布时间】:2019-07-19 05:23:00
【问题描述】:

我编写了一个将对象添加到对象数组的方法。如果数组已满,它应该创建一个新数组并使用 Arrays.copyOf 将旧数组大小加倍。但是,它会成功增加数组大小,但它会用旧数组中最后一个对象的副本填充新插槽。

这是 ClassRoster 类的 add 方法:

void add(Student newStudent){
    int i=0;
    while(i != classSize){
        if(roster[i] == null{
            roster[i] = newStudent;
            break;
        }
        if(i>=roster.legnth){
            Student[] newRoster = Arrays.copyOf(roster, 2*roster.length);
            roster = newRoster;
        }
        i++;
    }
}

ClassRoster 类还有一个构造函数,该构造函数初始化为 10 的数组大小。

public class ClassRoster{
    private Student[] roster;
    final int SIZE = 10;


    public ClassRoster(){
       this.roster = new Student[SIZE];
    }

main 方法使用此方法从输入文本文件中添加 Student 对象:

ClassRoster firstRoster = new ClassRoster();
scan = new Scanner(inputFile).useDelimiter(",|\\n");
while(scan.hasNext()){
    String name = scan.next();
    int gradeLevel = scan.nextInt();
    int testGrade = scan.nextInt();
    Student newStudent = new Student(name,gradeLevel,testGrade);
    firstRoster.add(newStudent);
    System.out.printf(firstRoster.toString());
}

文本文件如下所示:

John,12,95
Mary,11,99
Bob,9,87
Larry,10,90
Steph,11,89
James,12,95
Susan,11,88
Harry,9,78
Ann,10,92
Holly,9,86
Sammy,12,75
Jen,11,90
Katrina,9,94

但是,程序会产生如下输出:

John,12,95
Mary,11,99
Bob,9,87
Larry,10,90
Steph,11,89
James,12,95
Susan,11,88
Harry,9,78
Ann,10,92
Holly,9,86
Holly,9,86
Holly,9,86
Holly,9,86

它似乎只是在旧数组达到其最大大小 10 后复制了旧数组的最后一个对象。在 Holly 之后,它不会打印出其余的学生。

解决方案

找出问题所在。该数组的大小从未翻倍或增加。该数组的大小仍然为 10,因为它永远不会在 add 方法中重新进入 while 循环,因为 while(i != classSize) 现在为 false。因此,代码永远不会到达方法的if (i>=roster.length) 部分,也不会增加数组的大小。该程序不断打印 Holly 的副本,因为 scan.hasNext() 是真的。它不断将数组中的最后一个对象返回给 System.out.printf(firstRoster.toString());。它只是打印到控制台,但实际上并未分配给数组中的索引。

对于解决方案,我只是修改了add方法中的while语句:

while(i != classSize || i >= roster.length)

【问题讨论】:

  • 如果数组赋值为空,为什么要保护它?如果你这样做,你似乎会把人扔掉。我不使用 Arrays.copyOf,所以我不知道在新创建的插槽中留下了什么。在该部分代码之前和之后转储数组可能会很有趣。
  • 您没有向我们展示您的实际代码,因为上面的代码甚至没有编译。 @JosephLarson Arrays.copyOf 将新插槽设置为 null。 (如果上面的代码被更正,所以它确实编译了,它显然会将所有 null 条目设置为 newStudent。)
  • @DavidConrad 这就是我的假设,但除了一个非常奇怪的数据转储方法之外,我无法弄清楚为什么他会看到他显示的输出。这可能是他的打印代码。
  • @DavidConrad@JosephLarson 我的错,忘记在帖子中添加主要代码。我编辑并添加了它。
  • 为什么不使用ArrayList 而不是自己尝试重新实现其行为?

标签: java arrays object dynamic copy


【解决方案1】:

如果classSizeroster.length 相同,那么当你将数组大小加倍时,你应该改变它的值(尽管你不应该保留一个单独的变量,因为你有roster.length,除非你需要它来做其他事情)。
当您将数组的大小加倍时,您可以在 classSize 位置添加新项目(classSize 仍然等于之前的大小)并打破循环:

void add(Student newStudent){
    int i=0;
    while(i != classSize){
        if(roster[i] == null{
            roster[i] = newStudent;
            break;
        }
        if(i >= roster.legnth){
            Student[] newRoster = Arrays.copyOf(roster, 2 * roster.length);
            roster = newRoster;
            roster[classSize] = newStudent;
            classSize = roster.length;
            break;
        }
        i++;
    }
}

【讨论】:

  • 它仍然给我同样的结果。我试过只使用 classSize 和 roster.length ,但还是一样。
  • 上述循环不能在数组中多次保存相同的newStudent 对象,因为一旦将其存储到某个位置,它就会退出循环。因此调试以查找在哪个点(如果存在)您多次保存相同的newStudent
【解决方案2】:

解决方案

找出问题所在。该数组的大小从未翻倍或增加。该数组的大小仍然为 10,因为它永远不会在 add 方法中重新进入 while 循环,因为 while(i != classSize) 现在为 false。因此,代码永远不会到达方法的if (i>=roster.length) 部分,也不会增加数组的大小。该程序不断打印 Holly 的副本,因为 scan.hasNext() 是真的。它不断将数组中的最后一个对象返回给System.out.printf(firstRoster.toString());。它只是打印到控制台,但实际上并未分配给数组中的索引。

对于解决方案,我只是修改了add方法中的while语句:

while(i != classSize || i >= roster.length)

【讨论】:

    猜你喜欢
    • 2015-06-03
    • 2013-02-27
    • 2016-12-10
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多