gpt4 book ai didi

java - ArrayList 的 removeRange 方法如何工作?

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:59:59 31 4
gpt4 key购买 nike

ArrayList 的 removeRange 工作很奇怪。检查下面的示例代码,我给反向输入。还以为名单被反删了。

例如:3 到 1 表示删除了三个元素(第 3、第 2 和第 1)。

但是,输出完全让我感到困惑。很想知道它是如何工作的?

从 JavaDoc 中,我找到了以下语句。如果toIndex < fromIndex,系统会抛出IndexOutOfBoundException,但不会。这是错误吗?

IndexOutOfBoundsException - if fromIndex or toIndex is out of range (fromIndex < 0 || fromIndex >= size() || toIndex > size() || toIndex < fromIndex)

import java.util.*;
public class TestRemoveRange extends ArrayList {

public static void main(String arg[]){

TestRemoveRange list = new TestRemoveRange();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");

System.out.println("before remove : " + list);

list.removeRange(3, 1);

System.out.println("after remove (3, 1) : " + list); //[a, b, c, b, c, d, e]


}
}

最佳答案

查看实际的源代码可能有助于澄清您的问题:

Java 8ArrayList.removeRange()看起来像这样:

protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);

// clear to let GC do its work
int newSize = size - (toIndex-fromIndex);
for (int i = newSize; i < size; i++) {
elementData[i] = null;
}
size = newSize;
}

Java 9ArrayList.removeRange()改为:

protected void removeRange(int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IndexOutOfBoundsException(
outOfBoundsMsg(fromIndex, toIndex));
}
modCount++;
shiftTailOverGap(elementData, fromIndex, toIndex);
}

private void shiftTailOverGap(Object[] es, int lo, int hi) {
System.arraycopy(es, hi, es, lo, size - hi);
for (int to = size, i = (size -= hi - lo); i < to; i++)
es[i] = null;
}

正如您在上面的代码片段中看到的,两种实现都使用了 System.arraycopy()删除列表的项目。但仅从 Java 9 开始,如果 fromIndex > toIndex 存在抛出 IndexOutOfBoundsException 的检查。

由于 System.arraycopy() is implemented native the source code在不同的平台上可能会有所不同。根据javadoc它应该是这样的:

Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array. [...]

If the src and dest arguments refer to the same array object, then the copying is performed as if the components at positions srcPos through srcPos+length-1 were first copied to a temporary array with length components and then the contents of the temporary array were copied into positions destPos through destPos+length-1 of the destination array.

对于 IndexOutOfBoundException 它说:

If any of the following is true, an IndexOutOfBoundsException is thrown and the destination is not modified:

  • The srcPos argument is negative.
  • The destPos argument is negative.
  • The length argument is negative.
  • srcPos+length is greater than src.length, the length of the source array.
  • destPos+length is greater than dest.length, the length of the destination array.

因此,如果您使用 Java 8 或更低版本运行您的示例,您可能会得到以下结果:

before remove : [a, b, c, d, e]
after remove (3, 1) : [a, b, c, b, c, d, e]

如果您使用 Java 9 或更高版本运行您的示例,您将遇到此异常:

before remove : [a, b, c, d, e]
Exception in thread "main" java.lang.IndexOutOfBoundsException: From Index: 3 > To Index: 1
at java.base/java.util.ArrayList.removeRange(ArrayList.java:769)
at TestRemoveRange.main(TestRemoveRange.java:16)

关于java - ArrayList 的 removeRange 方法如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56707203/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com