我有以下两种情况:
1。 int值作为参数
int intNum = 2;
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.remove(intNum);
System.out.println(list.size());
// output: 2
2。长值作为参数
long longNum = 2;
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.remove(longNum);
System.out.println(list.size());
// output: 3
我在两种情况下都传递了2作为值,但是我获得了List的不同大小值。这种行为的实际原因是什么?
Properly removing an Integer from a List没有解释内置数据类型具有相同的值但行为与上面提到的不同
答案 0 :(得分:25)
<强>自动装箱强>
list.remove
方法重载,两个不同的签名用于不同的目的。一个list.remove(int)
根据索引删除项目,另一个list.remove(Object)
根据对象相等性删除项目。
您的第一个情况会触发第一个类型,而您的第二个示例(使用long longNum
)会触发第二个类型,将long
原语自动装箱到java.lang.Long
个对象。这不等于添加到列表中的java.lang.Integer
(自动装箱)值,因此不会从列表中删除任何内容,并且大小将保持不变。
答案 1 :(得分:5)
来自List.remove()documentation:
remove(int index)移除指定位置的元素 这个清单(可选操作)。
remove(Object o)删除指定元素的第一个匹配项 从该列表中,如果它存在(可选操作)。
removeAll(Collection c)从此列表中删除其所有元素 包含在指定集合中(可选操作)。
如果您的第二个示例确实很长,则不会被删除(因为它使用了第二个删除方法)。
答案 2 :(得分:5)
小心:第一个删除Integer
处的index = 2
。见ArrayList.remove(int)
第二个尝试使用ArrayList.remove(Object)
删除对象,但您要删除的对象不存在,因为它是Long
对象。
答案 3 :(得分:4)
List
界面包含两种remove()
方法 - remove(Object)
和remove(int)
。
Java 6中remove(Object)
的实现如下:
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;
}
Java 6中remove(int)
的实现是:
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) 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(int)
方法,该方法会删除指定索引处的对象。在这种情况下,您指定了索引2,实际上是值“3”。
在您的第二个示例中,您调用remove(Object)
方法,因为没有remove(long)
方法,long
将不会转换为int
}。基于remove(Object)
方法的实现,它查找对象相等性。由于您的列表包含Integer
类型的对象,并且您提供了Long
,因此没有任何内容可以与之匹配。
以下方法可能是正在发生的事情的一个更好的例子:
public static void main(String[] args) {
ArrayList<Integer> list;
System.out.println("Removing intNum");
int intNum = 2;
list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
System.out.println("List = " + list);
list.remove(intNum);
System.out.println("List = " + list);
System.out.println("Removing longNum");
long longNum = 2;
list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
System.out.println("List = " + list);
list.remove(longNum);
System.out.println("List = " + list);
}
此代码的输出为:
Removing intNum
List = [1, 2, 3]
List = [1, 2]
Removing longNum
List = [1, 2, 3]
List = [1, 2, 3]
答案 4 :(得分:3)
使用int参数调用List.remove()将匹配签名remove(int index)
,并且无论列表是否具有值为2的Integer项,都将删除索引list[2]
上的项。
使用long参数调用List.remove()将导致编译器对Long对象执行自动装箱并匹配签名remove(Object o)
。列表将迭代,询问o.equals(每个项目)和之前提到的,Long不等于Integer。
答案 5 :(得分:2)
当您执行list.remove(intNum);
时,它正在执行remove(int index);
类的List
签名,该签名将删除给定索引的项目。
但是当你list.remove(longNum);
(考虑到你的意思是longNum
为long
)时,它会执行boolean remove(Object o);
类List
签名,检查是否该对象存在于列表中,如果是,则将其删除。
由于列表是Integer
列表,因此找不到对象,也没有删除任何内容,这就是为什么第二个结果是3,没有删除任何内容。
答案 6 :(得分:2)
Collection中的List有两个重载方法 1. public E remove(int index) 2. public boolean remove(Object o)
在你的情况下,第二种方法被调用。因为你传递的时间很长(隐式转换为长包装器类所以对象类)。
现在List.remove(longNum)删除具有最低索引i的元素,使得(longNum == null?get(i)== null:longNum.equals(get(i)))(如果存在这样的元素) )。
现在在你的情况下,当计数器来到第二个位置(即i = 1)。 longNum.equals(get(1))返回 false ,因为get(1)返回值为= 2的java.lang.Integer的Object,longNum是java.lang.Long的一个实例,其值为= 2。所以equals方法返回false,因此它不会删除元素。
您可以按类名称
检查值的类型char