Java基础——删除集合中一个指定的元素
List<String> lst =new ArrayList<String>();
lst.add("b");
lst.add("b");
lst.add("a");
lst.add("c");
错误的操作1
for(int i=0;i<lst.size();i++)
{
if("b".equals(lst.get(i)))
{
lst.remove(i);
}
}
System.out.println(lst);
// 结果是 [b, a, c]
错误的操作2
for(Integer i=0;i<lst.size();i++)
{
if("b".equals(lst.get(i)))
{
lst.remove(i);
}
}
System.out.println(lst);
// [b, b, a, c]
错误的操作1是由于没有注意删除时后面元素往前移,for的指针往后移问题。
正确的操作:
- 1.使用for删除一个元素时进行回调,ArrayList的底层结构是数组类型,数组这种数据结构的特点是删除其中某个元素时,后面的所有元素索引都会前移,此时for循环的指针却会下移,因此会略过下一个元素,解决方案是删除时将指针回调一次。
for(int i=0;i<lst.size();i++)
{
if("b".equals(lst.get(i)))
{
lst.remove(i);
i--;
}
}
- 2 . 使用迭代器来操作
Iterator it=lst.iterator();
while(it.hasNext())
{
if(it.next().equals("b"))
{
it.remove();
}
}
问题2中的探索
问题2的原因是定义循环的索引为Integer类型,关于remove我们可以看源码,ArrayList.java中有两个remove函数。
// 索引是int类型
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
// 索引是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;
}
//fastremove
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
也就是说,如果是对象类型,那么就去查找elementData中的值与这个对象类型值是equals的元素,并且fastremove。如果我们传入Integer类型的 0或者1,我们插入的元素并没有这个,所以就不会删除“b”了。