在Java中交换两个变量

2025/04/19

1. 概述

有时,我们可能想在代码中交换两个变量。

在本教程中,我们将根据要交换的变量类型,介绍几种不同的方法。然后,我们将测试每种方法的性能。

2. 简单方法:使用临时变量

交换两个变量的最简单方法是使用第3个变量作为临时存储:

Object a, b;
Object temp;
temp = a;
a = b;
b = temp;

这种方法特别易于阅读和理解,即使对于初学者来说也是如此,它的主要缺点是它需要一个临时变量。

我们应该记住,这种方法是唯一可以交换Object变量的方法

2.1 为什么不换一种方法?

如果我们必须在代码中的几个点交换变量,那么创建一个像这样交换变量的方法可能听起来很有吸引力:

public void swap(Object a, Object b)

不幸的是,这在Java中不起作用,因为在方法调用期间会复制对对象的引用

如果我们确实想要一个交换方法,必须在你的对象周围使用一个包装类并交换包装器中包含的对象

private class Wrapper {
    public String string;
}

以及交换方法:

private static void swap(Wrapper a, Wrapper b) {
    String temp = b.string;
    b.string = a.string;
    a.string = temp;
}

使用此方法,封闭的字符串在方法返回后仍将保持交换。

3. 不使用临时变量

如果我们的变量是原始类型,我们可以找到不使用临时变量的方法来交换它们。

让我们看几个例子。

3.1 使用算术运算

我们可以用数学方法交换变量,而无需使用临时变量,方法有很多种;以下示例假设我们要交换两个整数a = 5和b = 10。

我们可以使用加法和减法来交换:

a = a + b;  // a = 15
b = a - b;  // b = 5
a = a - b;  // a = 10

或者,我们可以使用乘法和除法:

a = a * b;  // a = 50
b = a / b;  // b = 5
a = a / b;  // a = 10

需要注意的是,如果任何一个数字为0,此方法将不起作用,因为第一个操作会导致存储0,从而使算法的其余部分失效。此外,如果b = 0,则会因除以0而引发ArithmeticException

我们还应该注意基本类型类型的容量,因为加法/乘法运算可能导致数字超过基本类型类型的最大值,这可能会导致交换后出现错误,而不会引发任何异常

例如,如果a = Integer.MAX_VALUE,则交换之前a = 2147483647和b = 10,交换之后a = 10,b = -1。

如果我们使用char、byte或short类型的数据,则需要进行显式转换,因为算术运算符的结果至少在Java中是int类型的值:

a = (char)(a + b);
b = (char)(a - b);
a = (char)(a - b);

3.2 使用逻辑运算

如果我们处理的是整数数据类型(例如char、short、byte、int、long),我们可以使用异或按位运算符(XOR),“^”运算符将对变量的所有位进行按位异或运算:

a = a ^ b;  // a = 1111 (15)
b = a ^ b;  // b = 1010 (5) 
a = a ^ b;  // a = 0101 (10)

我们应该知道,与算术运算符一样,按位异或运算符至少返回int数据类型。因此,如果我们处理chars、bytes或shorts变量,则必须对每一行的异或结果进行强制类型转换。

3.3 单行变体

我们可以使用单行版本的交换方法来减少代码量:

b = (a + b)  (a = b);
a += b  (b = a);
a = a * b / (b = a);
a = a ^ b ^ (b = a);

这是因为表达式的求值遵循运算符的优先级,如果最初a = 5且b = 10,则最后一个表达式等价于a = 5 ^ 10 ^ (b = 5)。第一个运算(5 ^ 10)恰好是多行算法的第一行,然后我们将5赋值给b(括号优先),最后,我们计算15 ^ 5,这恰好是算法的第三行。

4. 性能分析

我们刚刚看到,在Java中交换两个变量的方法有很多种,但哪一种效率更高呢?为了了解每种算法的性能趋势,我们执行了变量交换方法的循环,并测量了交换两个变量100000次所需的时间。我们运行了10次测试,以计算每种算法的平均执行时间。结果如下:

绝对时间在这里并不重要,因为它取决于运行测试的机器。我们只看到一些算法比其他算法慢,乘法/除法尤其如此,无论是在单行版本中还是在多行版本中,它的运行速度都明显较慢。相反,XOR算法在多行和单行版本中都是最高效的。

使用临时变量交换对象也非常有效,这是可以理解的,因为在这种情况下只需要操作指针。

5. 总结

在本文中,我们研究了如何根据变量的类型在Java中交换两个变量。

我们描述了如何交换对象,然后研究了几种交换原始类型的方法和几种算法。最后,我们分析了每种方法的性能。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章