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

时间:2010-12-26 14:25:36

标签: java collections overloading

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

List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(6);
list.add(7);
list.add(1);

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

在处理整数列表时,区分remove(int index)remove(Object o)之间的正确方法是什么?@Nikita mentioned在给定索引中删除元素,而{{3}}在引用整数列表时通过引用删除元素?


这里要考虑的要点是{{3}} - 精确参数匹配优先于自动装箱。

8 个答案:

答案 0 :(得分:214)

Java始终调用最适合您的参数的方法。只有在没有施放/自动装箱的情况下才能调用的方法时,才会执行自动装箱和隐式上传。

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

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

这意味着list.remove(1)删除了位置1的对象,remove(new Integer(1))从该列表中删除了第一次出现的指定元素。

答案 1 :(得分:67)

你可以使用施法

list.remove((int) n);

list.remove((Integer) n);

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

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

答案 2 :(得分:10)

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

list.remove(int_parameter);

删除给定位置的元素和

list.remove(Integer_parameter);

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

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

答案 3 :(得分:7)

list.remove(4)list.remove(int index)完全匹配,因此会被调用。如果您想致电list.remove(Object),请执行以下操作:list.remove((Integer)4)

答案 4 :(得分:4)

  

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

没有必要猜测。第一种情况将导致List.remove(int)被调用,位置1的元素将被删除。第二种情况将导致调用List.remove(Integer),并且将删除其值等于Integer(1)的元素。在这两种情况下,Java编译器都会选择最接近的匹配重载。

是的,这里可能存在混淆(和错误),但这是一个相当不常见的用例。

当在Java 1.2中定义了两个List.remove方法时,重载不是模糊的。问题只出现在Java 1.5中引入泛型和自动装箱。在后视中,如果其中一个删除方法被赋予不同的名称会更好。但现在已经太晚了。

答案 5 :(得分:2)

请注意,即使VM没有做正确的操作,您仍然可以通过使用remove(java.lang.Object)对任意对象进行操作的事实来确保正确的行为:

myList.remove(new Object() {
  @Override
  public boolean equals(Object other) {
    int k = ((Integer) other).intValue();
    return k == 1;
  }
}

答案 6 :(得分:1)

我确实喜欢按照#decitrig在接受的回答第一条评论中的建议。

binary(2)

这对我有帮助。再次感谢#decitrig的评论。对某些人来说可能会有所帮助。

答案 7 :(得分:0)

这就是诀窍。

我们在这里举两个例子:

public class ArrayListExample {

public static void main(String[] args) {
    Collection<Integer> collection = new ArrayList<>();
    List<Integer> arrayList = new ArrayList<>();

    collection.add(1);
    collection.add(2);
    collection.add(3);
    collection.add(null);
    collection.add(4);
    collection.add(null);
    System.out.println("Collection" + collection);

    arrayList.add(1);
    arrayList.add(2);
    arrayList.add(3);
    arrayList.add(null);
    arrayList.add(4);
    arrayList.add(null);
    System.out.println("ArrayList" + arrayList);

    collection.remove(3);
    arrayList.remove(3);
    System.out.println("");
    System.out.println("After Removal of '3' :");
    System.out.println("Collection" + collection);
    System.out.println("ArrayList" + arrayList);

    collection.remove(null);
    arrayList.remove(null);
    System.out.println("");
    System.out.println("After Removal of 'null': ");
    System.out.println("Collection" + collection);
    System.out.println("ArrayList" + arrayList);

  }

}

现在让我们看一下输出:

Collection[1, 2, 3, null, 4, null]
ArrayList[1, 2, 3, null, 4, null]

After Removal of '3' :
Collection[1, 2, null, 4, null]
ArrayList[1, 2, 3, 4, null]

After Removal of 'null': 
Collection[1, 2, 4, null]
ArrayList[1, 2, 3, 4]

现在让我们分析一下输出:

  1. 当从集合中删除3时,它会调用集合的remove()方法,该方法将Object o作为参数。因此它删除了对象3。 但是在arrayList对象中,它被索引3覆盖,因此删除了第4个元素。

  2. 通过相同的Object删除逻辑,在第二个输出中的两种情况下都会删除null。

  3. 因此,要删除作为对象的数字3,我们将明确需要将{3}作为object传递。

    这可以通过使用包装器类Integer进行转换或包装来完成。

    例如:

    Integer removeIndex = Integer.valueOf("3");
    collection.remove(removeIndex);