?> 前言
经常使用一些循环,进行耗时计算的操作,特别是 for 循环,它是一种重复计算的操作,如果处理不好,耗时就比较大,如果处理书写得当,将大大提高效率,下面总结几条 for 循环的常见优化方式。
首先初始化一个集合 list,如下:
List<String> list = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
list.size()
int size = list.size();
for (int i = 0; i < size; i++) {
System.out.println(list.get(i));
}
list.size()
for (int i = 0, size = list.size(); i < size; i++) {
System.out.println(list.get(i));
}
for (int i = list.size() - 1; i >= 0; i--) {
System.out.println(list.get(i));
}
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
for (String o : list) {
System.out.println(o);
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10000; j++) {
}
}
?> 分支优化规则
引入流水线工作机制以后,为了配合流水线工作,处理器增加了一个分支目标缓冲器(Branch Target Buffer)。在流水线工作模式下,如果遇到分支结构,就可以利用分支目标缓冲器预测并读取指令的目标地址。分支目标缓冲器在程序运行时将动态记录和调整转移指令的目标地址,可以记录多个地址,对其进行表格化管理。当发生转移时,如果分支目标缓冲器中有记录,下一条指令在取指令阶段就会将其作为目标地址。如果记录地址等于实际目标地址,则并行成功;如果记录地址不等于实际目标地址,则流水线被冲洗。同一个分支,多次预测失败,则更新记录的目标地址。因此,分支预测属于 “经验主义” 或 “机会主义",会存在一定的误测。
基于上述原因,大家以后在编写多重循环时应该把大循环放到内层,这样可以增加分支预测的准确度,如下面的示例所示:
int[][] a = new int[10][10000];
for (int i = 0; i < 10; i++) {
// 下面每次循环会预测成功9999次
// 第1次没有预测,最后退出循环时预测失败1次这样的
// 过程重复10次
for (int j = 0; j < 10000; j++) {
a[i][j]++;
}
}
for (int j = 0; j < 10000; j++) {
// 下面每次循环会预测成功9次
// 第1次没有预测,最后退出循环时预测失败1次
// 这样的过程重复10000次
for (int i = 0; i < 10; i++) {
a[i][j]++;
}
}
// 前:
int a = 10, b = 11;
for (int i = 0; i < 10; i++) {
i = i * a * b;
}
// 后:
int c = a * b;
for (int i = 0; i < 10; i++) {
i = i * c;
}
反例:
for (int i = 0; i < 10; i++) {
try {
} catch (Exception e) {
}
}
正例:
try {
for (int i = 0; i < 10; i++) {
}
} catch (Exception e) {
}