str==null,null==str,str!=null,null!=str性能比较

LiuDonghua 发布于 2011/05/29 08:57
阅读 2K+
收藏 0

以前看别人写的代码,有些人总是用null==str,null!=str来代替str==null,str!=null,那时候没太注意,今天没事就来测试一下!从网上找了一个简单的测试代码(并非原创),自己也修改了一下.

(测试环境Win8M2+MyEclipse8.5+JDK7)

代码如下

import org.junit.Test;

public class JavaTest {
	@Test
	public void isNull() {
        String str =null;
        long len = 100000000;
        ////////////////////
        long startTime1 = System.currentTimeMillis();
        for(long i = 0; i < len; i++) {
            if(null!=str){}
        }
        long endTime1 = System.currentTimeMillis();
        System.out.println("null!=str: "+ (endTime1 - startTime1) +"ms");
        ///////////////////////////////
        long startTime2 = System.currentTimeMillis();
        for(long i = 0; i < len; i++) {
            if(str!=null){}
        }
        long endTime2 = System.currentTimeMillis();
        System.out.println("str!=null: "+ (endTime2 - startTime2) +"ms");
        ///////////////////////
        long startTime3 = System.currentTimeMillis();
        for(long i = 0; i < len; i++) {
            if(null==str){}
        }
        long endTime3 = System.currentTimeMillis();
        System.out.println("null==str: "+ (endTime3 - startTime3) +"ms");
        //////////////////////
        long startTime4 = System.currentTimeMillis();
        for(long i = 0; i < len; i++) {
            if(str==null){}
        }
        long endTime4 = System.currentTimeMillis();
        System.out.println("str==null: "+ (endTime4 - startTime4) +"ms");
        ////////
    }
}
经过多次测试,结果如下

第一次:

null!=str: 225ms

str!=null: 152ms

null==str: 151ms

str==null: 153ms

第二次:

null!=str: 223ms

str!=null: 152ms

null==str: 151ms

str==null: 152ms

第三次: null!=str: 224ms str!=null: 153ms null==str: 153ms str==null: 152ms
然后使len添加一个0,测试结果如下! 第一次: null!=str: 2211ms str!=null: 1515ms null==str: 1513ms str==null: 1516ms 第二次:null!=str: 2225ms str!=null: 1515ms null==str: 1515ms str==null: 1516ms

第三次:

null!=str: 2217ms str!=null: 1515ms null==str: 1514ms str==null: 1514ms
由于时间关系就简单的测试了,初步得出一下结论:str==null,null==str性能差不多,几乎相等;str!=null,null!=str性能差距有些大,str!=null有优于null!=str。 即使把上面str换成一个非null字符串结果也很相似,与str为null时各项对比不超过5ms/10ms.
所以个人建议不管从程序可读性还是性能上来说,推荐使用str!=null,str==null这种形式。 也欢迎各位发表意见或看法!


以下是话题补充:

@LiuDonghua:这个排版有些问题,发帖时那个效果不是这样的,呵呵~~~ (2011/05/29 08:59)
加载中
0
SeekerLee
SeekerLee
貌似没啥意义
0
魔君
魔君

兄弟测试环境牛

window8 、 jdk7

0
xyz555
xyz555

这个无关执行速度问题。

把null放左边是为了防止将==误写为=(逻辑符号写为赋值符号)。

这样如果写错ide就会报错。

0
liuex
liuex

1、为啥要和JUnit扯上关系?既然是做性能测试的话,当然是越干净越好。

2、测试环境,关键的CPU/内存/操作系统jdk是32还是64位这些指标都米有啊。。。。。

另外,我把循环次数改成10亿次,在本地机器上面跑了一下:

null!=str: 670ms
str!=null: 672ms
null==str: 671ms
str==null: 670ms
在我的机器上几乎没有差别啊,没有性能优化一说。

楼主的数据中,执行1亿次最大才相差70毫秒,我认为这点性能差别实在不值得关注。

 

我的测试环境: 

amd athlon II  640

ddr3 2G X2

win 7 64bit sp1

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)

Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode) 使用默认参数

0
liuex
liuex

引用来自“xyz555”的答案

这个无关执行速度问题。

把null放左边是为了防止将==误写为=(逻辑符号写为赋值符号)。

这样如果写错ide就会报错。

我觉得这种写法更多的还是从C/C++继承来的。

Java不会像C/C++那样把其他类型的表达式自动隐式转换成bool类型,而是编译器直接报告语法错误。

但是一个例外是boolean类型的变量赋值,赋值语句是右结合的,编译器检测不出来是否是手误。

比如:if ( some_flag = true){...}

如果手误少写一个=号,编译仍然能通过的,但是语义就变了。

0
烈冰
烈冰
lz的测试环境本身就存在很多不确定因素
0
liuex
liuex

想起来以前看到一个测试循环性能的:

1、for( int i=0;i<Integer.MAX_VALUE;i++){...}

2、for(int i=Integer.MAX_VALUE; i !=0; i--){...}

sun/ibm/bea的jdk,运行(2)都比运行(1)会稍微快一点点。但是这样的性能优化基本没有价值,很少有人采用。

 

另外还有使用循环展开的方式,可以微弱的提高CPU的流水线效率,在C/C++/Java程序中都能一定程度上提高性能,但是也很少有人使用:这种优化带来的性能提高远不如带来的麻烦多。

 

我一直觉得,近年来随着硬件性能的提高,软件工程的地位超过了程序性能的地位。大家都更加喜欢可阅读、可维护、容易维护的程序。

0
L
LiuDonghua

引用来自“liuex”的答案

1、为啥要和JUnit扯上关系?既然是做性能测试的话,当然是越干净越好。

2、测试环境,关键的CPU/内存/操作系统jdk是32还是64位这些指标都米有啊。。。。。

另外,我把循环次数改成10亿次,在本地机器上面跑了一下:

null!=str: 670ms
str!=null: 672ms
null==str: 671ms
str==null: 670ms
在我的机器上几乎没有差别啊,没有性能优化一说。

楼主的数据中,执行1亿次最大才相差70毫秒,我认为这点性能差别实在不值得关注。

 

我的测试环境: 

amd athlon II  640

ddr3 2G X2

win 7 64bit sp1

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)

Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode) 使用默认参数

嗯,我的电脑配置是没说清楚,不过现在也没必要了,还有就是以后测试要使用一些稳定的测试环境,不能像我一样使用最新的而非主流、稳定的。

还有就是同意楼下说的,现在随着硬件的提升,绝大多数程序良好的可读性要高于提升的那一点点性能。

所以我还是坚持使用str==null,str!=null形式,至于为了防止str=null而采用null==str这种方式初学者可以使用,但对于编程有两三年的程序员应该避免。

0
xyz555
xyz555

引用来自“liuex”的答案

引用来自“xyz555”的答案

这个无关执行速度问题。

把null放左边是为了防止将==误写为=(逻辑符号写为赋值符号)。

这样如果写错ide就会报错。

我觉得这种写法更多的还是从C/C++继承来的。

Java不会像C/C++那样把其他类型的表达式自动隐式转换成bool类型,而是编译器直接报告语法错误。

但是一个例外是boolean类型的变量赋值,赋值语句是右结合的,编译器检测不出来是否是手误。

比如:if ( some_flag = true){...}

如果手误少写一个=号,编译仍然能通过的,但是语义就变了。

将常量写在逻辑表达式的左边目的就是防止错误的将逻辑符号写为赋值符号,Java的确是个例外。

而将常量写在逻辑表达式的左边是应该养成的一个良好编码风格的习惯。

0
liuex
liuex

引用来自“LiuDonghua”的答案

引用来自“liuex”的答案

1、为啥要和JUnit扯上关系?既然是做性能测试的话,当然是越干净越好。

2、测试环境,关键的CPU/内存/操作系统jdk是32还是64位这些指标都米有啊。。。。。

另外,我把循环次数改成10亿次,在本地机器上面跑了一下:

null!=str: 670ms
str!=null: 672ms
null==str: 671ms
str==null: 670ms
在我的机器上几乎没有差别啊,没有性能优化一说。

楼主的数据中,执行1亿次最大才相差70毫秒,我认为这点性能差别实在不值得关注。

 

我的测试环境: 

amd athlon II  640

ddr3 2G X2

win 7 64bit sp1

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)

Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode) 使用默认参数

嗯,我的电脑配置是没说清楚,不过现在也没必要了,还有就是以后测试要使用一些稳定的测试环境,不能像我一样使用最新的而非主流、稳定的。

还有就是同意楼下说的,现在随着硬件的提升,绝大多数程序良好的可读性要高于提升的那一点点性能。

所以我还是坚持使用str==null,str!=null形式,至于为了防止str=null而采用null==str这种方式初学者可以使用,但对于编程有两三年的程序员应该避免。

我遇到的比较NB的做Java的人,几乎都是从C/C++转过来的,也许是那些人习惯了,比较的时候总是喜欢把常量/右值放在前面,变量放在后面。

我觉得既然是程序风格的问题,只要一个团队保持一致就可以。

说句题外话,似乎有深厚的C/C++基础是成为NB的Javaer的必要条件,我觉得。Java加上虚拟机这一层后,程序性能的分析和优化都变得相当困难。

返回顶部
顶部