这是一个很经典的题目,面试考试经常碰到,这种场景一般出现在排序中。
我们知道交换两个数有很多写法,总归分为四种:中间值交换、加减交换、运算交换、异或交换,网上有很多关于它们的说法,很多人有异或交换比中间值交换慢的说法,我表示怀疑,因为初学java时就知道位运算在java虚拟机里运算速度是最快的,所以我打算模仿他们的实验进行验证,实验方式很简单,对同一组数进行一亿次循环交换,看它们执行的总时长。
int x = 2,y = 3;
Integer count = 10000*10000;
long start = System.currentTimeMillis();
System.out.println("中间值交换法交换"+count+"次:开始时间:"+start);
int t = 0;
for(int i=0;i<count;i++){
t = y;
y = x;
x = t;
}
long end = System.currentTimeMillis();
System.out.println("中间值交换法交换"+count+"次:结束时间:"+end);
System.out.println("中间值交换法交换"+count+"次:消耗时间:"+(end-start));
start = System.currentTimeMillis();
System.out.println("异或交换法交换"+count+"次:开始时间:"+start);
for(int i=0;i<count;i++){
x = x^y;
y = x^y;
x = x^y;
}
end = System.currentTimeMillis();
System.out.println("异或值交换法交换"+count+"次:结束时间:"+end);
System.out.println("异或值交换法交换"+count+"次:消耗时间:"+(end-start));
结果是一个惊喜,的确,一亿次交换异或交换确实要比中间值交换运行时间长,但是如果是一千万次、一百万次、十万次运算异或运算则要比中间值交换快很多,至于一万次,运算速度太快捕获不到更精确的时间。基本上可以证明异或交换其实是比中间值交换快的。至于为什么会在超大数据的情况下异或运算花费更多时间还需要进一步研究。以下是另外两种交换的写法
加减交换
x = x+y;
y = x-y;
x = x-y;
这种方式弊端相当明显,两个值比较大的情况可能超出本身类型的最大值。
运算交换
x = y + (y=x)*0;
也有这种写法
x = (x+y) - (y=x);
这种方式用最短的代码完成数值交换,看起来很神奇,其实华而不实。