转载:
Java优化集合代码的一些方法
我们平常在开发中都会用到很多的集合类,但是在使用的时候会有很多自己都不怎么注意的小习惯会影响一些效率,这次就介绍一下优化集合代码的一些小方法;
一、分离循环中被重复调用的代码
假设我们要循环一个数组,最简单的方法如下:
for (String value : strings) {
// Do something useful here
}
当每次代码运行到这个循环时,如果 strings 变量是一个
Iterable 的话,代码将会自动创建一个
Iterator 的实例。如果使用的是 ArrayList 的话,虚拟机会自动在堆上为对象分配3个整数类型大小的内存。
private class Itr implements Iterator<E> {
int cursor;
int lastRet = -1;
int expectedModCount = modCount;
// ...
所以一般建议使用等价循环的方式
for(int i=0;i<strings.length;i++){
}
这里;i<strings.length每次都会去调用,并且每次都返回相同的数值,分离所有类型的代码对提升循环性能有积极的意义,因此可以改写成:
int count=strings.length;
for(int i=0;i<count;i++){
}
二、减少方法调用
方法调用是会消耗系统堆栈的,虽然面向对象设计模式和模块化的软件设计方法鼓励程序员使用若干小方法取代一个大方法,但是这样一般都是以牺牲系统性能为代价的。这有赖于编译器的优化以降低性能损失。
在应用程序中继承JDK中的Collection实例并对其进行扩展时,应当尽可能得避免调用原生接口,转为直接访问对象的属性。
int count = 0;
String s=null;
int colsize = this.elementCount; //代替size()方法
for (int i = 0; i < colsize; i++) {
if ((s = (String)elementData[i].indexof("north") != -1) || //取代get方法
(s.indexof("west") != -1)||
(s.indexof("south") != -1)) {
count++;
}
}
原本的size()和get()方法被取代为直接访问原始变量,性能有成倍提高。
三、RandomAccess接口
RandomAccess接口是一个标志接口,本身并不提供任何方法,任何实现RandomAccess接口的类都可视作支持快速访问的类,在JDK中任何一个基于数组实现的List(ArrayList、Vector)都实现了RandomAccess接口,因此支持对数组的快速随机访问,而链表实现的List需要进行链表遍历,如下:
Object o;
if (list instanceof RandomAccess) {
for (int i = 0, n = list.size(); i < n; i++) {
o = list.get(i);
} else {
Iterator itr = list.iterator();
for (int i = 0, n = list.size(); i < n; i++) {
o = itr.next();
}
}
}
代码首先判断是否是可以随机访问的,如果支持随机访问则使用get方法,否则采用迭代器的方式访问。这对于集合的访问速率提升有很大帮助。
四、使用entrySet()
当我们遍历一个键值对的Map时,最简单的方法如下
当我们遍历一个键值对的Map时,最简单的方法如下
for (K key : map.keySet()) {
V value : map.get(key);
}
最高效的方法应该如下
for (Entry<K, V> entry : map.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
}
在我们的集合中应该谨慎的使用Map,如果必须要使用的话最好使用entrySet()去迭代!这样的话,我们要访问的就仅仅是Map.Entry的实例。