六十、性能考虑,数组是首选
基本类型是在栈内存中操作的,而对象则是在对内存中操作的。栈内存的特点是速度快,容量小,对内存的特点是速度慢,容量大。
注意:性能要求较高的场景中使用数组替代集合。
六十一、若有必要,使用变长数组
数组扩容代码如下:
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是相等的,与具体容量类型无关。