实践 39:不要使用 Enumeration或 Iterato r来遍历 Vector
Java供遍历vector元素的数种办法:
1. Iterator(选代器)
2. ListIerator(list迭代器)
3. Enumeration(枚举器)
4. get()函数(取值函数, getter)
import java.util.Enumeration;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;
public class LoopVector {
public int enumVec(Vector vec) {
int total = 0;
Enumeration enums = vec.elements();
while(enums.hasMoreElements()) {
total += ((Integer)enums.nextElement()).intValue();
}
return total;
}
public int iterVec(Vector vec) {
int total = 0;
Iterator iter = vec.iterator();
while(iter.hasNext()) {
total += ((Integer) iter.next()).intValue();
}
return total;
}
public int listIterVec(Vector vec) {
int total = 0;
ListIterator iter = vec.listIterator();
while(iter.hasNext()) {
total += ((Integer)iter.next()).intValue();
}
return total;
}
public int forVec(Vector vec) {
int total = 0;
int size = vec.size();
for (int i = 0; i < size; i++) {
total += ((Integer) vec.get(i)).intValue();
}
return total;
}
public static void main(String[] args) {
int VEC_SIZE = 100000;
Vector<Integer> vec = new Vector<>(VEC_SIZE);
for (int i = 1; i <= VEC_SIZE; i++) {
vec.add(i);
}
long startTimer = 0;
long endTimer = 0;
int res = 0;
LoopVector lv = new LoopVector();
startTimer = System.currentTimeMillis();
res = lv.enumVec(vec);
endTimer = System.currentTimeMillis();
System.out.println("invoke enumVec: res = " + res + ", cost=" + (endTimer-startTimer));
startTimer = System.currentTimeMillis();
res = lv.iterVec(vec);
endTimer = System.currentTimeMillis();
System.out.println("invoke iterVec: res = " + res + ", cost=" + (endTimer-startTimer));
startTimer = System.currentTimeMillis();
res = lv.listIterVec(vec);
endTimer = System.currentTimeMillis();
System.out.println("invoke listIterVec: res = " + res + ", cost=" + (endTimer-startTimer));
startTimer = System.currentTimeMillis();
res = lv.forVec(vec);
endTimer = System.currentTimeMillis();
System.out.println("invoke forVec: res = " + res + ", cost=" + (endTimer-startTimer));
}
}
传入同一个vector,以上四个函数完成相同的任务.返回一样的结果。其中三个函数有不同的性能: Iterator版和 ListIterator版的性能大致相同, Enumeration版大约快 l 2%。至于采用Vectorget()的标准循环版本,比其他三个函数快 29%—34%.
invoke enumVec: res = 705082704, cost=7
invoke iterVec: res = 705082704, cost=8
invoke listIterVec: res = 705082704, cost=9
invoke forVec: res = 705082704, cost=5
实践 40:使用 System.arraycopy()来复制 arrays
copyAray2()比copyArray1()体积小,因为它毕竟是使用函数调用来完成工作,而非使用 inline方式。由于 copyArray2()调用的 System.arraycopy()是以本机函数( native method)实现的,因此它的执行速度更快。由于它是本机函数,所以它可以直接、
高效地移动[原始 array]的内在内容到[目标 array]。这个动作之快速足以消减本机函数的调用代价,明显比一般Java代码快得多。但也由于它是一个本机函数( nativemethod) ,所以这个调用动作的执行速度在不同的平台上有所不同。
public class CopyArrayTest {
public void copyArray1(int[] src, int[] dest) {
int size = src.length;
for (int i = 0; i < size; i++) {
dest[i] = src[i];
}
}
public void copyArray2(int[] src, int[] dest) {
int size = src.length;
System.arraycopy(src, 0, dest, 0, size);
}
public static void main(String[] args) {
int ARRAY_SIZE = 100000000;
int[] src = new int[ARRAY_SIZE];
int[] dest1 = new int[ARRAY_SIZE];
int[] dest2 = new int[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++) {
src[i] = i;
dest1[i] = 0;
dest2[i] = 0;
}
CopyArrayTest cat = new CopyArrayTest();
long startTimer = 0;
long endTimer = 0;
startTimer = System.currentTimeMillis();
cat.copyArray1(src, dest1);
endTimer = System.currentTimeMillis();
System.out.println("copyArray1, dest[ARRAY_SIZE-1] = " + dest1[ARRAY_SIZE-1] + ", timer = " + (endTimer - startTimer));
startTimer = System.currentTimeMillis();
cat.copyArray2(src, dest2);
endTimer = System.currentTimeMillis();
System.out.println("copyArray2, dest[ARRAY_SIZE-1] = " + dest2[ARRAY_SIZE-1] + ", timer = " + (endTimer - startTimer));
}
}
/*
copyArray1, dest[ARRAY_SIZE-1] = 99999999, timer = 97
copyArray2, dest[ARRAY_SIZE-1] = 99999999, timer = 87
*/
实践41:优先使用 array,然后才考虑Vector和ArrayList
Vector和 ArrayList都采用 array作为底部设施,所以当这些 classes调整自身大小的时候,会创建一个新的 array, 然后将所有元素从原先的 array复制到新的 array中, 而后便可加入原本放不下的新元素了。
Vector和 ArrayList还有另一个不太起眼的副作用。 无论什么时候, 如果要从它们之中移除 ( removed)一个元素,所有[下标大于被删除元素]者都需要向前(向着起始处)移动一格。这样可以使得底部的 array不至于留下[空洞](holes)。
Vector的 get()是 synchronized,可以自动调整;----速度最慢
ArrayList的get()是unsynchronized,可以自动调整;----速度次之
Array不可以自动调整;-------速度最快
import java.util.ArrayList;
import java.util.Vector;
public class LoopArray {
public void iterateArray(int[] arr) {
int size = arr.length;
int j;
for (int i = 0; i < size; i++) {
j = arr[i];
}
}
public void iteratorVector(Vector vec) {
int size = vec.size();
Object j;
for (int i = 0; i < size; i++) {
j = vec.get(i);
}
}
public void iterateArrayList(ArrayList alt) {
int size = alt.size();
Object j;
for (int i = 0; i < size; i++) {
j = alt.get(i);
}
}
public static void main(String[] args) {
int SIZE=1000000;
int[] arr = new int[SIZE];
Vector vec = new Vector(SIZE);
ArrayList alt = new ArrayList(SIZE);
for (int i = 0; i < SIZE; i++) {
arr[i] = i;
vec.add(i);
alt.add(i);
}
long startTimer = 0;
long endTimer = 0;
LoopArray la = new LoopArray();
startTimer = System.currentTimeMillis();
la.iterateArray(arr);
endTimer = System.currentTimeMillis();
System.out.println("iterateArray timer = " + (endTimer - startTimer));
startTimer = System.currentTimeMillis();
la.iteratorVector(vec);
endTimer = System.currentTimeMillis();
System.out.println("iteratorVector timer = " + (endTimer - startTimer));
startTimer = System.currentTimeMillis();
la.iterateArrayList(alt);
endTimer = System.currentTimeMillis();
System.out.println("iterateArrayList timer = " + (endTimer - startTimer));
}
}
/*
iterateArray timer = 3
iteratorVector timer = 8
iterateArrayList timer = 4
*/
实践 42:尽可能复用(reuse)对象
创建对象,代价不菲(参见实践32) ,因此你应该尽量减少创建次数。复用既有对象,而不重新创建一个。
class Employee {
private String name;
private String title;
private int salary;
public Employee() {}
public Employee(String name, String title, int salary) {
this.name = name;
this.title = title;
this.salary = salary;
}
public void reinitialize(String name, String title, int salary) {
this.name = name;
this.title = title;
this.salary = salary;
}
public String getName() {return this.name;}
public void setName(String name) {this.name = name;}
public String getTitle() {return this.title;}
public void setTitle(String title) {this.title = title;}
public int getSalary() {return this.salary;}
public void setSalary(int salary) {this.salary = salary;}
}
public class EmployeeTest {
public int computePayroll1(String[] name, String[] title, int[] salary) {
int size = name.length;
int totalPayroll = 0;
for (int i = 0; i < size; i++) {
Employee em = new Employee(name[i], title[i], salary[i]);
totalPayroll += em.getSalary();
// System.out.println("computePayroll1: " + name[i] + ", " + title[i]+ ", " + salary[i] + "," + em.getSalary());
}
return totalPayroll;
}
public int computePayroll2(String[] name, String[] title, int[] salary) {
int size = name.length;
int totalPayroll = 0;
if(size > 0)
{
Employee em = new Employee();
for (int i = 0; i < size; i++) {
em.setName(name[i]);
em.setTitle(title[i]);
em.setSalary(salary[i]);
totalPayroll += em.getSalary();
// System.out.println("computePayroll2: " + name[i] + ", " + title[i]+ ", " + salary[i] + "," + em.getSalary());
}
}
return totalPayroll;
}
public int computePayroll3(String[] name, String[] title, int[] salary) {
int size = name.length;
int totalPayroll = 0;
if(size > 0)
{
Employee em = new Employee();
for (int i = 0; i < size; i++) {
em.reinitialize(name[i], title[i], salary[i]);
totalPayroll += em.getSalary();
// System.out.println("computePayroll3: " + name[i] + ", " + title[i]+ ", " + salary[i] + "," + em.getSalary());
}
}
return totalPayroll;
}
public static void main(String[] args) {
int SIZE = 100000;
String[] name = new String[SIZE];
String[] title = new String[SIZE];
int[] salary = new int[SIZE];
for (int i = 0; i < SIZE; i++) {
name[i] = Integer.toString(i);
title[i] = Integer.toString(i);
salary[i] = i;
}
EmployeeTest et = new EmployeeTest();
long startTimer = 0;
long endTimer = 0;
int totalPayroll = 0;
startTimer = System.currentTimeMillis();
totalPayroll = et.computePayroll1(name, title, salary);
endTimer = System.currentTimeMillis();
System.out.println("computePayroll1, totalPayroll=" + totalPayroll + ", timer=" + (endTimer-startTimer));
totalPayroll=0;
startTimer = System.currentTimeMillis();
totalPayroll = et.computePayroll2(name, title, salary);
endTimer = System.currentTimeMillis();
System.out.println("computePayroll2, totalPayroll=" + totalPayroll + ", timer=" + (endTimer-startTimer));
totalPayroll=0;
startTimer = System.currentTimeMillis();
totalPayroll = et.computePayroll3(name, title, salary);
endTimer = System.currentTimeMillis();
System.out.println("computePayroll3, totalPayroll=" + totalPayroll + ", timer=" + (endTimer-startTimer));
}
}
/*
computePayroll1, totalPayroll=704982704, timer=19
computePayroll2, totalPayroll=704982704, timer=12
computePayroll3, totalPayroll=704982704, timer=7
*/