前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间拜读了秦小波老师的《改善Java程序的151建议》,感觉廓然开朗,注意到了很多平时在编写代码中并不会注意的问题,甚至感觉自己对Java只是略懂皮毛,不足以登大雅之堂,特此与读者分享读书笔记,以下内容摘自《改善Java程序的151建议》一书和笔者的理解 Java高质量代码系列文章 面向对象篇:http://ray-yui./blog/1926984 数据类型篇:http://ray-yui./blog/1927251 字符串篇:http://ray-yui./blog/1927647 数组与集合(1):http://ray-yui./blog/1928170 数组与集合(2):http://ray-yui./blog/1930155 好吧,本来是非常繁忙的星期五,但笔者公司的DB服务器又down了,文章时间又来了,上一章由于时间限制只讲了一半,下面继续书接上回 10.子列表只是原列表的视图 List接口中,提供了subList方法,作用就是返回一个列表中的子列表,这个方法与String类型的substring有点类似,请观察以下代码 Java代码
我们可以把List接口中的subList想成和数据库中的视图一样,在数据库中虽然不建议我们对视图进行增删改,但确实是可以操作的,而且操作完也可以反映到表当中,subList也同理,它只是原列表的视图,所有的操作都将直接影响原列表,但subList和数据库视图有一点不同,下面将会进行说明 11.推荐使用subList处理局部列表 现在有一个需求,在一个长度为50的列表中删除位置是10~20的元素 Java代码
以上方法2,为什么要不停删除位置为10的元素呢?这是很容易忽略的问题,因为List当删除元素时,为了保持有序性,会移动元素替换被删除的位置,所以当位置为10的元素删除后,11的位置会替换上来..在上面已经提到,修改子列表会直接影响原列表,使用方法2的一行就能完成,是不是很方便? 12.生成子列表后不要再操作原列表 subList生成子列表是原列表的视图,而对子列表的改动会直接影响原列表,那若然是对原列表的更改呢? Java代码
看到这个异常,很多人会觉得很郁闷,并发修改异常?可我程序并没有运行在多线程的环境当中,而原因是因为,当创建subList时,list会将1个变量modCount传递到subList的构造参数当中,而当list进行修改时,就会对modCount进行累加,而subList在进行操作时,会检查modCount是否和list的一致,若然不一直就抛出异常,这就是原因,这也是subList和数据库视图不同的地方,表修改后直接反应到视图,而list修改后,不会反应到subList,所以在使用subList时,应该使用如下方式对list进行加锁 Java代码
使用以上方式就可以明确表示,此列表是只读,当对列表进行操作时,就会抛出异常,增强了语义,而一个List可以有多个subList,但只要存在一个subList,就不能对原List进行操作.请谨记 13.使用Comparator进行排序 我们都知道,在集合类中要排序时,可以使用JDK提供的帮助工具,例如 Collections中的sort方法对List进行排序,亦可以使用Tree的数据结构来进行排序,例如Set接口中的TreeSet,TreeMap,使用Tree结构来进行排序时,是需要对象拥有比较性的,我们可以在实体类中实现Comparable<T>接口,但排序的方式是多变的,有时经过一段时间后,需求变了,需要按另外一个元素进行排序,但修改了已经稳定的实体类是不应该的,我们可以使用Comparator来进行排序,请看以下代码 Java代码
无论是Collections的sort方法和TreeMap,TreeSet都会有重载的方式,接受一个Comparator(比较器),此时有可以在这里进行元素比较的定义 14.使用binarySearch需要注意 binarySearch(二分查找)是性能较高的一种查找方式,通常我们使用的indexOf为顺序查找,当查找到匹配的值时马上返回,但若然此集合的元素数量多的话,使用顺序查找就性能就会降低,特别是当要查找的元素位于集合的末尾时,效率更低,而二分查找是将数据折半然后进行查找,没有找到指定元素时再折半,但需要注意,二分查找必须保持集合的有序性,所以在开发当中,若要使用二分查找,需先将集合进行排序.这点务必注意 15.集合中元素equlas和compareTo必须同步 在刚才提及的binarySearch和indexOf两种查找当中,有一点是非常不同的,indexOf的查找的时候是使用equlas来进行匹配,equlas返回为true时认为找到元素,而binarySearch是使用compareTo进行匹配,当compareTo返回0时认为找到元素,而当一个用户实体当中,equlas是使用用户名来重写equlas判断,而compareTo使用密码来比较,那将会导致不必要的错误 16.集合运算时,使用更优雅的方式 在集合的操作当中,经常会出现两个集合的 并集(or),交集(and),差集(not)等的操作,当然我们可以遍历两个集合,对比元素求出我们需要的并集交集差集等运算的结果,但这种方式处理,真的是最方便?最简单?最优雅?请看以下代码 Java代码
17.使用shuffle打乱列表 现在我们有一个需求,做一个扑克游戏,54张扑克存储到一个集合当中,每次发牌之前,都需要打乱一下扑克的顺序,这样的需求,我们可以有多种实现方式,使用Random来随机调整集合位置,或者集合的位置顺序交换,可有更优雅的方式吗? Java代码
18.多线程时使用Vetor或HashTable 通过查看JDK API可以发现,Vetor和HashTable是JDK1.0时已存在的类,他们是线程安全的,可在多线程的环境下使用 总结: 笔者在本文章中只从《改善Java程序的151建议》中提取部分进行归纳性叙述,推荐各位读者购买这本书,该书不仅从事例中学习,而且涉及到原理,底层的实现,不仅告诉你应该怎么做,还告诉你为什么要这样做. |
|