如何实现java中List中的remove(Object obj)方法?

时间:2014-04-09 19:50:31

标签: java list arraylist linked-list

有人可以将remove(Object obj)方法的实现赋予java中的List吗?

这个重载方法的定义方式和位置是什么?ArrayList中的实现是什么?

问题的第二部分是ArrayListLinkedList remove(int index)方法在ArrayList中工作得更快,因为底层实现(一个是数组和其他链接列表) 。但是删除(对象obj)方法呢?哪一个会更快?因为根据我的理解,两者都需要同时。在ArrayList中,迭代将在连续的内存位置上,而对于LinkedList则不会。但是我们必须基本迭代每个元素并使用equals检查需要获取哪个对象。

编辑:

我只是想知道为什么我会问这个问题。我们经常要求频繁插入和删除哪个列表最好使用。对此我非常困惑。如果我们使用remove(int index)方法ArrayList可以跳转到该位置(移动底层指针并删除对象)然后移动元素,而对于LinkedList它需要从headNode遍历到索引并将nextNode更改为指向更高的值。哪个更快,为什么?一些信息:当我们开始使用remove(Object o)方法时会发生什么? When to use LinkedList over ArrayList?

2 个答案:

答案 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中删除(对象)的速度会更快。