0

我想ArrayList通过遍历它并将每个元素复制到新列表中的特定位置来重新排列它。

在这种情况下,我想将一个元素移动到列表的末尾。例如,如果列表是 ABCDE 并且 j == B,那么新列表应该是 ACDEB。

这是我的代码:

private ArrayList<Job> schedule;
private ArrayList<Job> tempSchedule;

...

schedule = input;
tempSchedule = new ArrayList<Job>(schedule.size());

...

private void moveJob(int j) {
    for(int i = 0; i < schedule.size(); i++) {
        if(i == j) { //move to the end
            tempSchedule.set(schedule.size()-1, schedule.get(i));
        } else {
            if(i > j && i <= schedule.size() -1) { //move one position back
                tempSchedule.set(i - 1, schedule.get(i));
            } else { //same position
                tempSchedule.set(i, schedule.get(i));
            }
        }
    }
    schedule = tempSchedule;
    u++;
}

现在我得到一个IndexOutOfBoundsException: Index: 0, Size: 0at tempSchedule.set

我想问题出在这条线上

tempSchedule = new ArrayList<Job>(schedule.size());

还请解释如何制作深拷贝。

编辑:感谢所有答案。我通过简单地删除该项目并在最后添加它来运行它,就像建议的那样。

我想构建一个新列表的原因是因为我可能不得不在某些时候进行更复杂的重新排列。

4

6 回答 6

3

首先,阅读有关 ArrayList 和集合的 javadoc。

new ArrayList(capacity) 不会复制,它只是分配具有该容量的列表。要复制列表(它不是克隆,它是引用副本,您需要再次回到基础)将是 new ArrayList(oldArrayList)。

其次,您的测试的大小为 0,因此其中没有对象,因此 get(0) (正确并按照规范)会抛出索引越界异常,因为您的列表为空。

除此之外,set 和 get 都不会修改列表,因此如果您正确创建了副本并且它的内容是 ABCD 并且您执行了该操作,那么它的内容将是 ABCB。你想要的是。

X = tempSchedule.remove(i) // removes element at I
tempSchedule.add(X)        // adds element to end of list
于 2014-11-20T13:19:22.267 回答
1

问题是您的tempSchedule列表是空的。set()覆盖给定位置的元素。如果您的列表为空,则无法执行此操作。

自从你写了这可能有点令人困惑new ArrayList<Job>(schedule.size())。但是您传递的参数没有设置大小,而是设置了初始容量,即底层数组的初始大小,可以在调整大小之前使用。

于 2014-11-20T13:16:39.343 回答
1

原因是当您使用时间表大小定义 arrayList 时,它是一个空列表,即不包含任何内容。

因此,当您尝试设置一个元素(用于替换现有元素)时,它会将索引与列表的大小进行比较,发现索引为 0,大小也为 0。

请注意,仅通过将 size 作为构造函数传递,您不会更改 arrayList 的大小。所以为了避免这种情况,你需要使用:

tempSchedule = new ArrayList<Integer>(schedule);

代替

tempSchedule = new ArrayList<Integer>(schedule.size());
于 2014-11-20T13:17:37.747 回答
1

tempSchedule初始化为空:

tempSchedule = new ArrayList<Job>(schedule.size());

你不能set在空的ArrayList. 它期望您要替换的索引已经有一个值。

您在这一行中得到异常 - tempSchedule.set(i, schedule.get(i));- when i==0

set调用RangeCheck

/**
 * Checks if the given index is in range.  If not, throws an appropriate
 * runtime exception.  This method does *not* check if the index is
 * negative: It is always used immediately prior to an array access,
 * which throws an ArrayIndexOutOfBoundsException if index is negative.
 */
private void RangeCheck(int index) {
if (index >= size)
    throw new IndexOutOfBoundsException(
    "Index: "+index+", Size: "+size);
}

如您所见,您传递给它的索引必须小于列表的当前大小。

于 2014-11-20T13:16:04.050 回答
1

正如其他所有答案所述,您有语法谬误。
我更关心你的方法。

你不能简单地做:

private void moveJob(int j) {
    Job toMove = tempSchedule.get(j);
    tempSchedule.remove(j);
    tempSchedule.add(toMove);
}

或者更简洁:

private void moveJob(int j) {
    tempSchedule.add(tempSchedule.remove(j));
}
于 2014-11-20T13:21:16.497 回答
1

你有,IndexOutOfBoundsException因为你schedule.size在你的 for 循环中使用它,而null你必须使用它tempSchedule.size

当你必须比较i and j时,你是在比较tempSchedule.get(i) and j

于 2014-11-20T13:21:41.537 回答