Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从列表中正确删除整数<;整数>;_Java_Collections_Overloading - Fatal编程技术网

Java 从列表中正确删除整数<;整数>;

Java 从列表中正确删除整数<;整数>;,java,collections,overloading,Java,Collections,Overloading,这是我刚刚遇到的一个很好的陷阱。 考虑整数列表: List<Integer> list = new ArrayList<Integer>(); list.add(5); list.add(6); list.add(7); list.add(1); List List=new ArrayList(); 增加(5); 增加(6); 增加(7); 增加第(1)款; 执行list.remove(1)时会发生什么?如何删除(新的整数(1))?这会引起一些讨厌的虫子 在处理整数列

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

List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(6);
list.add(7);
list.add(1);
List List=new ArrayList();
增加(5);
增加(6);
增加(7);
增加第(1)款;
执行
list.remove(1)
时会发生什么?如何删除(新的整数(1))?这会引起一些讨厌的虫子

在处理整数列表时,如何正确区分从给定索引中删除元素和通过引用删除元素



这里考虑的主要问题是一个精确的参数匹配优先于自动装箱。

< P>我不知道“正确”的方法,但是你建议的方法很好:

list.remove(int_parameter);
移除给定位置处的元素并

list.remove(Integer_parameter);
从列表中删除给定对象

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

您可以使用强制转换

list.remove((int) n);

不管n是int还是Integer,该方法总是调用您期望的方法

使用
(Integer)n
Integer.valueOf(n)
新整数(n)
更有效,因为前两个可以使用整数缓存,而后两个总是创建一个对象。

列表。remove(4)
列表完全匹配。remove(int index)
,因此将调用它。如果要调用
list.remove(Object)
请执行以下操作:
list.remove((Integer)4)

对执行列表时发生的情况有任何有根据的猜测。删除(1)?那么list.remove(新的整数(1))呢

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

是的,这里有可能出现混淆(和bug),但这是一个相当罕见的用例


当Java 1.2中定义了两个
List.remove
方法时,重载并不含糊。这个问题只是在Java1.5中引入泛型和自动装箱之后才出现的。事后看来,如果其中一个remove方法被赋予不同的名称会更好。但是现在已经太晚了。

请注意,即使虚拟机没有做正确的事情,也可以通过使用
remove(java.lang.Object)
操作任意对象来确保正确的行为:

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

Java总是调用最适合您的论点的方法。只有在没有强制转换/自动强制转换的情况下,无法调用任何方法时,才会执行自动强制转换和隐式向上转换

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

  • 删除(对象o)
  • remove(int索引)

这意味着
list.remove(1)
删除位置1处的对象,并
remove(新整数(1))
删除此列表中第一个出现的指定元素。

我只是按照接受答案第一条注释中的#decitrig建议做了如下操作

list.remove(Integer.valueOf(intereger_parameter));

这对我有帮助。再次感谢您的评论。这可能对某些人有所帮助。

好吧,这里是诀窍

让我们举两个例子:

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]
  • 从集合中删除3时,它将调用集合的
    remove()
    方法,该方法将
    对象o
    作为参数。因此,它将删除对象
    3
    。 但在arrayList对象中,它被索引3覆盖,因此第4个元素被删除

  • 通过相同的对象删除逻辑,在两种情况下,在第二个输出中都会删除null

  • 因此,要删除数字
    3
    ,这是一个对象,我们需要明确地将3作为
    对象传递

    这可以通过使用包装器类
    Integer
    进行强制转换或包装来实现

    例如:


    如果您能解释为什么会出现这种情况,那就太好了:)[autoboxing conditions…]通过使用强制转换,您可以确保编译器看到您期望的类型。在第一种情况下,'(int)n'只能是int类型,在第二种情况下,'(Integer)n'只能是Integer类型n'将根据需要进行转换/装箱/取消装箱,否则您将收到一个编译器错误。答:这里的真正问题是Sun公司的某些人不知何故认为在原语周围拥有(不可变)包装类是聪明的,后来有人认为拥有自动-(un)装箱更聪明。。。当存在更好的API时,人们仍然使用蹩脚的默认API。在很多方面,有比新的Arraylist更好的解决方案。例如,Trove提供了一个TIntArrayList。我用Java编写的程序越多(从2001年开始使用SCJP),我使用的包装类就越少,使用的API就越多(我想到了Trove、Google等)。选择一个关键点:
    Integer.valueOf(1)
    新整数(1)
    更好。静态方法可以进行缓存等操作,因此您将获得更好的性能。Peter Lawrey的建议更好,并避免了不必要的对象创建。@assylias:Peter Lawrey的建议与decitrig的建议完全相同,只是透明度更低。@MarkPeters我的评论是关于
    新整数(1)
    ,但我同意
    Integer.valueOf(1)
    (Integer)1
    是等效的。感谢Petar,像你上面写的那样简单的
    (Integer)
    强制转换似乎是我最容易的方法。使用上一种方法时,它似乎返回布尔值。当尝试堆叠多个移除时,我得到一个错误,我不能对布尔值调用移除。这个“解决方案”打破了
    equals
    方法的契约,s
    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]
    
    Integer removeIndex = Integer.valueOf("3");
    collection.remove(removeIndex);