本博文为《编写高质量代码—改善Java程序的151个建议》一书的阅读笔记。该书从很多方面给予了编写高质量代码的宝贵经验。而且该书应该是那种开发经验越丰富,体会越深的书籍。在阅读过程中,从该书中收获良多,这里主要作下书籍笔记,有体会的地方加点自己的想法。受限于知识水平,部分内容还没能深刻体会,所以更多更好的内容和具体实例还需要从书中去找寻。
一、性能考虑,数组是首选
在Java中数组虽然没有List、Set、Map这些集合类用起来方便,但是在基本类型处理方面,数组还是占优势的,而且集合类的底层也是通过数组实现的。所以在性能要求高的场景中推荐使用数组而不是集合。
二、若有必要,使用变长数组
Java中的数组是定长的,声明后就不可以改变长度,在使用中非常不方便。但是我们可以使用Arrays.copyOf实现数组动态扩容,这样既保证了效率,也提高了可用性。其实集合类的动态扩容也是同理。
三、警惕数组的浅拷贝
Arrays.copyOf方法产生的数组是一个浅拷贝,与序列化的浅拷贝、数组的clone方法、集合的clone方法一样都是浅拷贝:基本类型拷贝值,其他则拷贝引用。因此拷贝对象引用的值的修改也会影响被拷贝的对象的值,因为引用的是同一个地址。
四、在明确的场景下,为集合指定初始容量
集合类可以支持动态扩展长度,使用很方便,不过需要注意的是集合类实际存储使用的是数组,动态扩容也是通过Arrays.copyOf进行的。执行add操作时若默认长度不够时,会将集合的长度增加一定的倍数或长度(比如ArrayList会增加1.5倍),此时在数据量较大时进行拷贝会非常耗资源,效率也很低。
出于性能及资源使用考虑,在集合初始容量已知时,要直接初始为对应长度;在集合初始容量大概知道范围时,可以初始一个比最大值多一点的长度。
五、避开基本类型数组转换列表陷阱
书中举了一个非常好的例子,如下代码
int [] data = {1,2,3,3}; System.out.println(Arrays.asList(data).size());
结果打印出的结果却只有一条,因为asList方法的参数为泛型参数,而基本类型不能作为泛型参数,而int数组是一个对象,同时也是可以泛型化的,所以asList(data)最后实际是把数组对象转换成列表了,结果打印就是1条。
所以一定要注意基本数据类型数组不能做为asList的输入参数,否则会引起程序逻辑混乱。
六、asList方法产生的List对象不可更改
Arrays.asList方法产生的List对象为Arrays类中的静态内部类ArrayList,其修改内容的方法(add、remove)是继承自父类的,而父类的方法仅仅是抛出异常,所以一定要注意asList产生的不可更改,不然会抛异常。
七、不同的列表选用不同的遍历算法
对于支持随机存储(实现RandomAccess接口)的列表,使用下标遍历要比使用foreach遍历快些,在数据量大时尤为明显。而对于顺序存储的列表(例如LinkedList)此时使用foreach又比使用下标遍历效率高些。
具体原因与遍历的实现代码有关,foreach是通过iterator进行遍历的,可以这么理解随机遍历的列表本来就希望下标访问,所以下标访问更快。而有序列表是有顺序的,所以通过foreach一个个迭代效率更高。当然实际原因是实现逻辑的问题。
八、频繁插入和删除时使用LinkedList
这个在数据结构里面肯定提到过,ArrayList这种随机列表随机存取效率高,而LinkedList这种有序列表插入和删除效率更高。即对于列表增、删操作多的应该选用LinkedList,而对于列表修改多的应该选用ArrayList。
九、判断列表相等时只用关心集合是否相等
集合元素进行相等判断(equals)时,可能是不同的集合类型,但是只要集合里面的元素相等则两个集合相等。
十、子列表只是原列表的一个视图
subList产生的列表只是一个视图,所有列表的改动都会直接作用于原列表上。
十一、生成子列表后不要再操作原列表
通过subList生成子列表后,如果再操作原列表会导致subList产生的列表调用size方法时抛出异常。对于子列表,因为视图是动态生成的,生成子列表后再操作原列表,必须导致视图的不稳定性,所以生成子列表后,最好是通过Collections.unmodifiableList方法设置列表为只读状态,这样就能避免错误的发生。
十二、不推荐使用binarySearch对列表进行检索
对一个列表进行检索时,使用的最多的是indexOf方法,该方法是通过遍历进行查找的;Collections类还提供一个binarySearch方法进行检索,该方法是通过二分查找法进行查找的,但是二分查找法有一个前提需要注意,就是列表必须是有序的,不然查找的结果不准确。 因此对于有序列表,binarySearch方法可以优先考虑,而对于无序列表不推荐使用。
十三、集合中的元素必须做到compareTo与equals同步
如果对象实现了compareTo方法就应该覆写equals方法,确保两者同步,不然可能产生逻辑混乱。
十四、集合运算时使用更优雅的方式
例如求并集可以直接使用list1.addAll(list2);求交集可以直接使用list1.retainAll(list2);求差集(属于A但不属于B的集合叫做A与B的差集);求不重复的集合(A与B不重复的集合为A与B的并集去掉一份重复的A与B的交集,如果交集有的话)可以先删后加:list2.remove(list1),list1.addAll(list2)
十五、多线程使用Vector或HashTable
Vector是ArrayList的多线程版本,HashTable是HashMap的多线程版本。在多线程环境下更适用。
相关推荐
最近忙于学习SV,主要是数组,队列等代码笔记,加深理解 数组 array.rar 950 Bytes, 下载次数: 52 , 下
list,set,map的中不同子类的特点和使用方法
数组字符串笔记.30循环进阶\code1\数组字符串笔记
自己数组学习的笔记,把数组总结了一下,希望对入门学C++的同学有一定的作用,大神就不必看了,刚刚开始学
java数组与集合,主要内容包括笔记整理、小例子等等等,具体内容自个看
数组 08章笔记
《编写高质量代码:改善Java程序的151个建议》笔记
数组的声明方式和其它的变量是一样的,它可以使用 Dim、Static、Private 或 Public 语句来声明。标量变量(非数组)与数组变量的不同在于通常必须指定数组的大小。若数组的大小被指定的话,则它是个固定大小数组。若...
利用for循环把遍历数组中的元素依次获取出来 数组笔记及基本知识点.pdf 利用for循环把遍历数组中的元素依次获取出来 数组笔记及基本知识点.pdf 利用for循环把遍历数组中的元素依次获取出来 数组笔记及基本知识点.pdf...
这个文件里的内容适合Java初学者,里边包含了JavaSE阶段用到的多个数组以及集合的用法和声明方式。这也是小编在刚开学学习JavaSE时记录的一些笔记,里面的内容非常适合JavaSE入门者学习,都是浅显易懂的话语,没有太...
Numpy基础:数组和矢量计算-笔记与代码 对应代码
有关JAVA数组中方法的讲解,此教程为文档教程,此文档为JAVA中数组的上半部分。
编写高质量的Java代码word版本,相比于pdf版本,word版本更方便做笔记。
C语言指针数组函数笔记,自己总结的,希望有帮助
自己学习过程中记录的一些信息,可能不全C语言学习笔记变量数组指针C语言学习笔记变量数组指针C语言学习笔记变量数组指针C语言学习笔记变量数组指针C语言学习笔记变量数组指针C语言学习笔记变量数组指针
NULL 博文链接:https://rogerfederer.iteye.com/blog/783714
C++学习随笔,学写了C++的有关知识,有些代码敲打气啦比较费劲,现在分享一个数组的代码
集合笔记 list arraylist集合 linkedlist集合 set hashset集合 treeset集合 map hashmap集合 terrset集合 不可变集合
VBA数组学习笔记.pdf
JAVA学习笔记 Java知识点总结