Java开发之道
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第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 ()方法,该方法用于移除当前集合中的所有元素。