有人可以将remove(Object obj)
方法的实现赋予java中的List吗?
这个重载方法的定义方式和位置是什么?ArrayList
中的实现是什么?
ArrayList
和LinkedList
remove(int index)
方法在ArrayList
中工作得更快,因为底层实现(一个是数组和其他链接列表) 。但是删除(对象obj)方法呢?哪一个会更快?因为根据我的理解,两者都需要同时。在ArrayList
中,迭代将在连续的内存位置上,而对于LinkedList
则不会。但是我们必须基本迭代每个元素并使用equals检查需要获取哪个对象。
编辑:
我只是想知道为什么我会问这个问题。我们经常要求频繁插入和删除哪个列表最好使用。对此我非常困惑。如果我们使用remove(int index)
方法ArrayList
可以跳转到该位置(移动底层指针并删除对象)然后移动元素,而对于LinkedList
它需要从headNode遍历到索引并将nextNode更改为指向更高的值。哪个更快,为什么?一些信息:当我们开始使用remove(Object o)
方法时会发生什么?
When to use LinkedList over ArrayList?
答案 0 :(得分:3)
remove(int index)
ArrayList
上的remove(int index)
比LinkedList
上的ArrayList
更快,但事实并非如此。
为什么呢?您忽略了ArrayList
的最大成本之一:在删除元素后实际花费调整数组大小的费用。
此处提供public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
的实际实施:
System.arraycopy
现在,LinkedList
调用实际上正在完成将现有数组的一半复制到新内存中,将它们连续排列,然后自行清理的工作。实际上,在整个操作之后,每个元素都向左移动了一次。
无论执行此操作的位置(列表前面,列表中间,列表末尾),您都要将 n-1 元素复制到连续内存中。这是O(n)操作。
现在,与checkElementIndex
的实现进行比较/对比(public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
被省略,因为它很直观):
size >> 1
实现将从后面或从前面搜索,具体取决于哪个更接近(因此按位除以2,或ArrayList
)。实际上查找位置涉及到工作,但是一旦找到它,就会完成一个非常具体且不依赖于大小的步骤,以确保保留列表的完整性。
因此,无论我在哪里删除这一个元素(前面,中间,结尾),我都会做同样的工作单元来删除节点并调整我的列表。因此,运行时操作可以考虑恒定时间。
附录:
为了进一步阅读,在LinkedList
中添加元素的行为方式与删除元素的方式类似 - 您必须考虑到您的基础数组可能需要要在之前调整,您可以输入,如果输入10,000个元素并进行1,000次调整,则按照O(n)的顺序插入数据。
在{{1}}中插入对比度,只插入前端或末端;两者都可以直接访问,不涉及原始数组的任何内容,并且可以在不变的时间内完成。
答案 1 :(得分:-2)
在ArrayList中随机访问更好,但在LinkedList中元素搜索会更快(如果 元素数量为1kk +)。你可以查看:-)
这就是为什么在LinkedList中删除(对象)的速度会更快。