先看一段伪代码
if (condition) {
do if logic;
} else {
do else logic;
}
if else大家一定经常写,也很容易说出if else的执行逻辑:如果条件为真,执行if逻辑;如果条件为假,执行else逻辑。换句话说,要么执行if分支,要么执行else分支。但是,你有没有想过,if和else分支的执行概率都是50%吗?答案当然是不是。看一个例子
int i = 0, j = 0;
for(int k=0;k<10000;k++) {
int randInt = new Random().nextInt(100);
if(randInt < 30) {
i++;
} else {
j++;
}
}
System.out.println("i=" + i + ",j=" + j);
-------------
i=3015,j=6985
我们可以很容易的判断if分支的执行概率大约为30%,else分支的执行概率大约为70%。在进行一万次的模拟场景实验中,也得到了近似的结果。我们接着对代码进行一些改动
int i = 0, j = 0;
for(int k=0;k<10000;k++) {
int randInt = new Random().nextInt(100);
if(randInt >= 30) {
j++;
} else {
i++;
}
}
System.out.println("i=" + i + ",j=" + j);
-------------
i=3037,j=6963
我们通过修改if判断条件,等价于修改了if和else的位置。简单来说,第一段代码可以描述成经过一次条件判断,有30%的概率执行if分支,有70%的概率执行else分支;第二段代码可以描述成经过一次条件判断,有70%的概率执行if分支,有30%的概率执行else分支。我们假设if和else分支的执行开销是一样的,所以无论我们怎么写(大于等于30还是小于30),我们总的开销是不变的(以执行一万次来说,需要一万次判断以及一万次累加)。
我们明确了if else分支执行的概率并不是50%,并且在if和else互换位置的情况下,开销一样。这有什么用呢?看下面
static int m = 0;
static int n = 0;
public static void main(String[] args) {
int i = 0, j = 0, l = 0;
for(int k=0;k<10000;k++) {
int randInt = new Random().nextInt(100);
if(ifJudge(randInt)) {
j++;
} else if(elseIfJudge(randInt)) {
i++;
} else {
l++;
}
}
System.out.println("i=" + i + ",j=" + j + ",l=" + l);
System.out.println("m=" + m + ",n=" + n);
}
public static boolean ifJudge(int randInt) {
m++;
if(randInt < 20) {
return true;
}
return false;
}
public static boolean elseIfJudge(int randInt) {
n++;
if(randInt < 50) {
return true;
}
return false;
}
-------------
i=2981,j=1991,l=5028
m=10000,n=8009
我们增加了else if分支,同时将if判断和else if判断抽成一个方法,在方法内部累加调用次数。在进行一万次的模拟场景实验中,我们总的分支逻辑开销没有变(一万次++操作),但是我们的if判断走了10000次,elseif判断走了近似8000次。也就是说我们的判断开销是18000。我们对代码进行修改,看下面
static int m = 0;
static int n = 0;
public static void main(String[] args) {
int i = 0, j = 0, l = 0;
for(int k=0;k<10000;k++) {
int randInt = new Random().nextInt(100);
if(ifJudge(randInt)) {
j++;
} else if(elseIfJudge(randInt)) {
i++;
} else {
l++;
}
}
System.out.println("i=" + i + ",j=" + j + ",l=" + l);
System.out.println("m=" + m + ",n=" + n);
}
public static boolean ifJudge(int randInt) {
m++;
if(randInt >= 50) {
return true;
}
return false;
}
public static boolean elseIfJudge(int randInt) {
n++;
if(randInt >= 20) {
return true;
}
return false;
}
------------
i=3050,j=4969,l=1981
m=10000,n=5031
我们修改了if判断和elseif判断的逻辑,但保持了上一段代码一样的执行逻辑。在进行一万次的模拟场景实验中,我们判断逻辑的开销从18000降到了15000。其实我们可以算出来,上一段代码if判断条件是<20,也就是有80%的概率会执行elseif判断;修改之后的代码if判断条件是>=50,也就是只有50%的概率会执行elseif判断。
所以大家平时写代码的时候,应该把执行概率最大的情况尽量放在前面。