今天我在写最小生成树的Prim算法的时候,发现了一个问题,我觉得值得探讨一下:
我使用一个ArrayList储存未加入最小生成树的节点的index(整数类型),每一次循环找到一个离已加入最小生成树的节点集合“最近”的节点,将它的index从这个ArrayList中删除。在检查程序逻辑无误后运行,发现抛出了java.lang.IndexOutOfBoundsException。
原因
简单检查后我发现ArrayList的remove方法是一个重载的(overloaded)方法。即:
从IDEA的代码提示可以看到,remove方法有两种参数类型,一种是int类型,一种是Object类型。如果你的ArrayList指定的元素类型是Integer,那么你使用remove方法移除一个Integer类型的元素的时候,程序可能理解成移除由该数字指定位置上的元素。
我进一步猜想线性容器应当都有通过index删除元素的方法,因此我查看了List接口的定义,其中果不其然有两个remove方法:
1. 按index移除元素:
E remove(int index);
// Search Operations
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*
* @param o element to search for
* @return the index of the first occurrence of the specified element in
* this list, or -1 if this list does not contain the element
* @throws ClassCastException if the type of the specified element
* is incompatible with this list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* list does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
*/
2.按元素移除:
boolean remove(Object o);
// Bulk Modification Operations
/**
* Returns <tt>true</tt> if this list contains all of the elements of the
* specified collection.
*
* @param c collection to be checked for containment in this list
* @return <tt>true</tt> if this list contains all of the elements of the
* specified collection
* @throws ClassCastException if the types of one or more elements
* in the specified collection are incompatible with this
* list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified collection contains one
* or more null elements and this list does not permit null
* elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #contains(Object)
*/
解决
因此,在编程的时候,应当严格区分Integer和int。如果你要从一个元素类型为Integer的List中删除一个元素(按照元素而不是index删除),你应该用以下两种方式的其中一种:
int elementToBeRemoved = 0;
list.remove((Integer)elementToBeRemoved);
或
Integer elementToBeRemoved = 0;
list.remove(elementToBeRemoved);