重新排列ArrayList的顺序

时间:2014-11-20 13:08:44

标签: java arraylist deep-copy call-by-value

我希望通过迭代ArrayList并将每个元素复制到新列表中的特定位置来重新排列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++; }

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

这是我的代码:

IndexOutOfBoundsException: Index: 0, Size: 0

现在我在tempSchedule.set

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

我猜问题就在于这一行

{{1}}

另请说明如何制作深层照片。

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

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

6 个答案:

答案 0 :(得分:3)

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

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

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

除此之外,既不设置也不获取将修改列表,因此如果您正确创建了副本并且其内容是ABCD并且您执行了该操作,那么它的内容将是ABCB。你想要的是什么。

X = tempSchedule.remove(i) // removes element at I
tempSchedule.add(X)        // adds element to end of list

答案 1 :(得分:1)

tempSchedule初始化为空:

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

您无法在空set上使用ArrayList。它期望您要替换的索引已经有一个值。

您在此行中获得例外情况 - tempSchedule.set(i, schedule.get(i)); - 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);
}

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

答案 2 :(得分:1)

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

自写new ArrayList<Job>(schedule.size())以来,这可能有点令人困惑。但是您传递的参数不会设置大小,而是initial capacity,这意味着底层数组的初始大小,可以在调整大小之前使用。

答案 3 :(得分:1)

原因是当你定义带有schedule大小的arrayList时,它是一个空列表,即什么都不包含。

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

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

tempSchedule = new ArrayList<Integer>(schedule);

而不是

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

答案 4 :(得分: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));
}

答案 5 :(得分:1)

您拥有IndexOutOfBoundsException因为您在for循环中使用了schedule.size,而null则必须使用tempSchedule.size

您需要比较i and j,而必须比较tempSchedule.get(i) and j