正确地从List <Integer>中删除整数

Yuv*_*dam 194 java collections overloading

这是我刚刚遇到的一个很好的陷阱.考虑一个整数列表:

List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(6);
list.add(7);
list.add(1);
Run Code Online (Sandbox Code Playgroud)

对你执行时会发生什么的任何有根据的猜测list.remove(1)?怎么样list.remove(new Integer(1))?这可能会导致一些令人讨厌的错误.

在处理整数列表时,区分remove(int index)哪个元素从给定索引remove(Object o)中删除元素以及通过引用删除元素的正确方法是什么?


这里要考虑的要点是提到@Nikita - 精确参数匹配优先于自动装箱.

aka*_*aka 218

Java总是调用最适合您的参数的方法.仅当没有可以在没有强制/自动装箱的情况下调用的方法时,才会执行自动装箱和隐式向上转换.

List接口指定了两个remove方法(请注意参数的命名):

  • remove(Object o)
  • remove(int index)

这意味着list.remove(1)删除位置1处的对象并remove(new Integer(1))从此列表中删除指定元素的第一个匹配项.

  • 挑选一个:`Integer.valueOf(1)`比`new Integer(1)`更好.静态方法可以进行缓存等,因此您将获得更好的性能. (106认同)

Pet*_*rey 68

你可以使用铸造

list.remove((int) n);
Run Code Online (Sandbox Code Playgroud)

list.remove((Integer) n);
Run Code Online (Sandbox Code Playgroud)

如果n是int或Integer并不重要,该方法将始终调用您期望的那个.

使用(Integer) nInteger.valueOf(n)new Integer(n)前两个更有效可以使用Integer缓存,而后者将始终创建一个对象.

  • 如果你能解释为什么会是这样的话会很好:) [autoboxing conditions ...] (2认同)

Nik*_*bak 10

我不知道'正确'的方式,但你建议的方式工作得很好:

list.remove(int_parameter);
Run Code Online (Sandbox Code Playgroud)

删除给定位置的元素和

list.remove(Integer_parameter);
Run Code Online (Sandbox Code Playgroud)

从列表中删除给定的对象.

这是因为VM首先尝试查找使用完全相同的参数类型声明的方法,然后才尝试自动装箱.


Pet*_*hev 7

list.remove(4)是一个完全匹配list.remove(int index),因此它将被调用.如果你想打电话,请list.remove(Object)执行以下操作:list.remove((Integer)4).


Ste*_*n C 5

对执行 list.remove(1) 时会发生什么有任何有根据的猜测吗?list.remove(new Integer(1)) 怎么样?

无需猜测。第一种情况会导致List.remove(int)被调用,并且position处的元素1会被移除。第二种情况会导致List.remove(Integer)被调用,并且值等于的元素Integer(1)会被移除。在这两种情况下,Java 编译器都会选择最接近的匹配重载。

是的,这里可能会出现混乱(和错误),但这是一个相当不常见的用例。

当这两个List.remove方法在 Java 1.2 中定义时,重载是明确的。这个问题仅在 Java 1.5 中引入泛型和自动装箱时出现。事后看来,如果为其中一种删除方法指定一个不同的名称,效果会更好。但现在已经太晚了。