哈哈,关于你这个问题,引用R大的一句话“Java这个地方的API设计确实不咋好”,如果想看看R大的回答,可以移步知乎: https://www.zhihu.com/question/29371504 ====下面是一些与主题“有关系又无关系”的内容,如果想直奔主题,看最后就行======= 关于这个问题产生的原因,个人认为是Java集合框架的一个设计缺陷。 首先,List作为一个“集合”,肯定是要从Collection接口继承的,于是乎,就有了: public interface List<E> extends Collection<E> 好,那么我们看看Collection接口有哪些内容吧:看到了么boolean remove(Object o);这个方法出现了。 然而,作为一个List,在“集合”的基础上,还需要拥有按照下标删除元素的能力,这个就是List所“特有”的,所以,在List接口中就有 E remove(int index); 然后,在AbstractList实现List时,它就要实现:注意下面那个remove方法的小三角 好啦,看完List,来个小插曲,我们看看Set的接口:清一色的小三角 ====== 好啦,不扯了,回归正题,既然我们知道了这两个方法的出现原因,那么就需要看看到底该用哪个了。 我们先来看看remove(int): /** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ 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; // Let gc do its work return oldValue; } 可以看到,这里面就是很常见的检查,移除,调整容量操作。 再来看看remove(Object)的: /** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns <tt>true</tt> if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }可以看到,这次的操作的时间复杂度就比较高了,需要遍历,然后找到值相等的对象,最终会调用fastRemove进行移除。 那fastRemove干了哪些事呢? /* * Private remove method that skips bounds checking and does not * return the value removed. */ private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work } 看注释,意思就是,这个跟Remove(int)差不多,就是不返回移除后的数据。 看来,Josh Bloch大牛,为了遵守Collection的约定,硬是实现了remove(Object)这么一个蛋疼的方法 是不是很“简单粗暴”?连Hash都没用(用了Hash还有HashSet干嘛,一个ArrayList包办) ========== 所以,对于ArrayList,还是按照它的价值来,用remove(int)这个方法吧。毕竟,根据对象移除对象,这个应该是Set做的事,别难为可怜的ArrayList了。。
好像用错例子了,LinkedList也一样的道理,lz可以按照同样的思路来过一遍 以下是LinkedList的remove(int)与remove(Object)的实现: /** * Removes the element at the specified position in this list. Shifts any * subsequent elements to the left (subtracts one from their indices). * Returns the element that was removed from the list. * * @param index the index of the element to be removed * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { checkElementIndex(index); return unlink(node(index)); } /** * Removes the first occurrence of the specified element from this list, * if it is present. If this list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * {@code i} such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element */ public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; }
看API知道有三个方法,重写了
(1)移除该List的第一个元素
(2)按照索引来移除元素,带参数
(3)按照指定对象来移除元素
https://www.zhihu.com/question/29371504
====下面是一些与主题“有关系又无关系”的内容,如果想直奔主题,看最后就行=======
关于这个问题产生的原因,个人认为是Java集合框架的一个设计缺陷。
首先,List作为一个“集合”,肯定是要从Collection接口继承的,于是乎,就有了:
public interface List<E> extends Collection<E>
好,那么我们看看Collection接口有哪些内容吧:看到了么boolean remove(Object o);这个方法出现了。
然而,作为一个List,在“集合”的基础上,还需要拥有按照下标删除元素的能力,这个就是List所“特有”的,所以,在List接口中就有
E remove(int index);
然后,在AbstractList实现List时,它就要实现:注意下面那个remove方法的小三角
好啦,看完List,来个小插曲,我们看看Set的接口:清一色的小三角
======
好啦,不扯了,回归正题,既然我们知道了这两个方法的出现原因,那么就需要看看到底该用哪个了。
我们先来看看remove(int):
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*
* @param index the index of the element to be removed
* @return the element that was removed from the list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
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; // Let gc do its work return oldValue;
}
可以看到,这里面就是很常见的检查,移除,调整容量操作。
再来看看remove(Object)的:
/**
* Removes the first occurrence of the specified element from this list,
* if it is present. If the list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns <tt>true</tt> if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return <tt>true</tt> if this list contained the specified element
*/
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}可以看到,这次的操作的时间复杂度就比较高了,需要遍历,然后找到值相等的对象,最终会调用fastRemove进行移除。
那fastRemove干了哪些事呢?
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
看注释,意思就是,这个跟Remove(int)差不多,就是不返回移除后的数据。
看来,Josh Bloch大牛,为了遵守Collection的约定,硬是实现了remove(Object)这么一个蛋疼的方法
是不是很“简单粗暴”?连Hash都没用(用了Hash还有HashSet干嘛,一个ArrayList包办)
==========
所以,对于ArrayList,还是按照它的价值来,用remove(int)这个方法吧。毕竟,根据对象移除对象,这个应该是Set做的事,别难为可怜的ArrayList了。。
以下是LinkedList的remove(int)与remove(Object)的实现:
/**
* Removes the element at the specified position in this list. Shifts any
* subsequent elements to the left (subtracts one from their indices).
* Returns the element that was removed from the list.
*
* @param index the index of the element to be removed
* @return the element previously at the specified position
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
/**
* Removes the first occurrence of the specified element from this list,
* if it is present. If this list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* {@code i} such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns {@code true} if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return {@code true} if this list contained the specified element
*/
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}