第2篇 陷阱与谬误——吸取前人的教训
用经验和推理跳出技术的陷阱
用事实和原理揭穿谬误的谎言
深入剖析陷阱与谬误
第3章 细说开发人员不可忽略的21个技术陷阱
在编程过程中发生错误是常有的事情,有些错误是完全可以避免的,而有些错误则好像程序设置的陷阱,稍不留神就会误入其中。
由于陷阱的存在,往往会给用户造成不可估计的损失,为此笔者根据多年的编程经验,对程序中可能出现的陷阱进行了讲解,通过本章学习,希望对编程人员有所帮助,可以减少由于程序中存在的陷阱而给用户造成的损失。
陷阱1 漏洞百出——使用for删除集合元素陷阱
1.陷阱产生的场景
for语句在程序开发中经常被用到,它语法简单、逻辑严谨,完全可以替代其他任何循环语法,所以说它的可应用范围最广泛。但在应用for语句时也要注意,该语句内部的局部自增或自减变量i若处理不当,可能给程序带来巨大隐患,比如在使用for语句删除集合中的元素时,就可能出现下面的情况。
例3.1 使用for删除集合元素时的陷阱。(光盘位置:光盘\MR\Instance\3\01\UseForApp)
import java. util. LinkedList; import java. util. List; public class Program { public static void main (String[] args) { List<String> tempList = new LinkedList<String>(); tempList. add ("A"); tempList. add ("B"); tempList. add ("C"); for (int i = 0; i < tempList. size (); i++) { tempList. remove (i); } if (tempList. size () > 0) { System.out. println ("\n剩余元素的个数为" + tempList. size ()+",具体元素有:"); for (String item : tempList) { System.out. println (item+" "); } } else { System.out. println ("已删除所有的元素!"); } } }
本实例的目的是使用for语句删除集合中的所有元素,上述代码中描述了使用remove ()方法按照元素的位置索引逐个删除元素,看起来似乎很完美,但运行结果却出人意料,程序运行结果如图3.1所示。
图3.1 使用for删除集合元素陷阱
说明
从执行结果中,可以得出这样的判定结论,集合中的元素B在for循环中并未得到执行remove ()方法。由于B元素的索引值为1,这足以说明在使用for语句删除集合元素的过程中发生了跳跃,并没有按照元素在集合中的原始顺序逐个地删除。
进一步分析发现,每当删除一个元素时,集合的size ()方法的值都会减小1,这将直接导致集合中元素的索引重新排序,进一步说,就是剩余所有元素的索引值都减小1,正如图3.2所示的那样,而for语句的局部变量i 仍然在递增,这必将导致删除操作发生跳跃,这就是问题的根源所在。
图3.2 集合元素删除示意图
提示
清除集合中元素的方法很多,本实例并不是仅仅为了说明如何删除集合的所有元素,而是通过对这种现象的分析,让读者体会在使用循环语句处理集合问题时应该注意什么。
2.陷阱的解决方法
从上面的分析可知,删除集合中的元素会导致剩余元素的索引重排序,但在完全删除元素之前,索引值为0的元素一直存在,这就是解决问题的一个着手点。解决问题的办法可这样考虑,在remove ()方法被执行后,就使局部变量i的值减少1,从而始终保持i的值为0,这样每次循环都删除索引值为0的元素,最终实现删除集合中的所有元素。改正后的主要代码如下:
for (int i = 0; i < tempList. size (); i++) { tempList. remove (i); //始终删除索引值为0的元素 i -= 1; //局部变量i的值减去1 }
技巧
要删除List集合中的所有元素,还可使用该泛型集合的clear ()方法,该方法用于移除当前集合中的所有元素。