关于if else你不知道的事儿

先看一段伪代码

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判断。

所以大家平时写代码的时候,应该把执行概率最大的情况尽量放在前面。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值