《编写高质量Java》(七)

六十、性能考虑,数组是首选

基本类型是在栈内存中操作的,而对象则是在对内存中操作的。栈内存的特点是速度快,容量小,对内存的特点是速度慢,容量大。
注意:性能要求较高的场景中使用数组替代集合。

六十一、若有必要,使用变长数组

数组扩容代码如下:

public static <T> T[] expandCapacity(T[] datas, int newLen){
    newLen = newLen < 0 ? 0 : newLen;

    return Arrays.copyOf(datas, newLen); 
}

六十二、 警惕数组的浅拷贝

通过copyOf产生的数组是一个浅拷贝,这与序列化的浅拷贝完全相同:基本类型是直接拷贝值,其他都是拷贝引用地址。需要说明的是数组的clone方法也是与此相同,也都是浅拷贝,集合的clone方法也都是浅拷贝。

六十三、在明确的场景下,为集合指定初始容量

ArrayList初始长度为10,当容量不够用时则自动扩容,每次扩充1.5倍。
Vector则提供了递增步长,代表每次数组扩容时要增加的长度,不设置此值则是容量翻倍。

六十四、多种最值算法,适时选择

求最大值为例,可以有两种方法:

  • 自行实现,快速查找最大值
  • 先排序,后取值。

但是如果要查找仅次于最大值的元素,该如何处理呢?要注意,数组的元素是可以重复的,最大值可能有多个。这时就需要一个特殊的排序算法了,先要剔除重复数据,然后再排序。数组不能剔除重复数据,但是Set集合可以,而且Set集合的子类TreeSet还能自动排序。代码如下:

public static int getSecond(Integer[] data){
    List<Integer> dataList = Arrays.asList(data);
    TreeSet<Integer> ts = new TreeSet<Integer>(dataList);
    return ts.lower(ts.last());
}

注意:最值计算时,使用集合最简单,使用数组性能最优。

六十五、避开基本类型数组转换列表陷阱

原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱。

六十六、asList方法产生的List对象不可更改

六十七、不同的列表选择不同的遍历方法

列表遍历不是那么的简单,其中很有“学问”, 适时选择最优的遍历方式,不要固话为一种。

六十八、 频繁插入和删除时用LinkedList

在修改操作上,LinkedList要比ArrayList要慢很多,特别是要进行大量的修改时,两者完全不在一个数量级上 。其底层是数组实现的。
LinkedList删除和插入效率高,因为其底层是双向链表实现的。
两者在增加元素上基本上没有什么区别。

六十九、列表相等只需关心元素数据

只要所有的元素相等,并且长度也相等就表明两个List是相等的,与具体容量类型无关。

推荐阅读更多精彩内容