49

如果没有我们可以通过引用传递的方法,我如何在 java 中创建我的交换函数?有人可以给我一个代码吗?

swap(int a, int b)
{
     int temp = a;
     a = b;
     b = temp;
}

但是由于java按值传递参数,因此更改不会反映回来。

4

8 回答 8

76

我认为这是最接近简单交换的方法,但它没有简单的使用模式:

int swap(int a, int b) {  // usage: y = swap(x, x=y);
   return a;
}

y = swap(x, x=y);

x它依赖于将传入swap之前y赋值给x,然后x返回赋值给的事实y

您可以使其通用并交换任意数量的相同类型的对象:

<T> T swap(T... args) {   // usage: z = swap(a, a=b, b=c, ... y=z);
    return args[0];
}

c = swap(a, a=b, b=c)
于 2013-12-15T21:28:07.943 回答
28

您不能创建方法交换,因此在调用swap(x,y)x 和 y 的值之后将被交换。您可以通过交换它们的内容来为可变类创建这样的方法¹,但这不会改变它们的对象身份,并且您无法为此定义通用方法。

但是,您可以编写一个方法来交换数组或列表中的两个项目,如果这是您想要的。

¹ 例如,您可以创建一个带有两个列表的交换方法,在执行该方法后,列表 x 将具有列表 y 的先前内容,而列表 y 将具有列表 x 的先前内容。

于 2010-03-06T20:02:18.643 回答
16

这取决于你想做什么。此代码交换数组的两个元素。

void swap(int i, int j, int[] arr) {
  int t = arr[i];
  arr[i] = arr[j];
  arr[j] = t;
}

像这样的东西交换了两个int[]长度相等的内容。

void swap(int[] arr1, int[] arr2) {
  int[] t = arr1.clone();
  System.arraycopy(arr2, 0, arr1, 0, t.length);
  System.arraycopy(t, 0, arr2, 0, t.length);
}

像这样交换两个的内容BitSet(使用XOR 交换算法):

void swap(BitSet s1, BitSet s2) {
  s1.xor(s2);
  s2.xor(s1);
  s1.xor(s2);
}

像这样交换某些类的xy字段Point

void swapXY(Point p) {
  int t = p.x;
  p.x = p.y;
  p.y = t;
}
于 2010-03-06T19:58:43.930 回答
8

显然,我没有足够的声誉点来评论Dansalmo的答案,但这是一个很好的答案,尽管名称错误他的答案实际上是一个 K-combinator。

int K( int a, int b ) {
    return a;
}

传递给 methods/ctors/etc 时,JLS 是特定于参数评估的。(在旧规格中不是这样吗?)

诚然,这是一个功能性的成语,但对于那些认识它的人来说已经足够清楚了。(如果你不理解你找到的代码,不要乱用它!)

y = K(x, x=y);  // swap x and y

K-combinator 是专门为这种事情设计的。AFAIK 没有理由不通过代码审查。

我的 0.02 美元。

于 2015-10-06T17:22:43.547 回答
2

AFAIS,没有人提到atomic reference

整数

public void swap(AtomicInteger a, AtomicInteger b){
    a.set(b.getAndSet(a.get()));
}

细绳

public void swap(AtomicReference<String> a, AtomicReference<String> b){
    a.set(b.getAndSet(a.get()));
}
于 2016-06-14T14:16:06.357 回答
1

我可能会做类似以下的事情。当然,有了丰富的 Collection 类,我无法想象在任何实际代码中都需要使用它。

public class Shift {
  public static <T> T[] left (final T... i) {
    if (1 >= i.length) {
      return i;
    }
    final T t = i[0];
    int x = 0;
    for (; x < i.length - 1; x++) {
      i[x] = i[x + 1];
    }
    i[x] = t;
    return i;
  }
}

用两个参数调用,它是一个交换。

它可以按如下方式使用:

int x = 1;
int y = 2;
Integer[] yx = Shift.left(x,y);

或者:

Integer[] yx = {x,y};
Shift.left(yx);

然后

x = yx[0];
y = yx[1];

注意:它自动装箱原语。

于 2010-03-07T00:19:10.047 回答
1

试试这个魔法

public static <T> void swap(T a, T b) {
    try {
        Field[] fields = a.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object temp = field.get(a);
            field.set(a, field.get(b));
            field.set(b, temp);
        }
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

并测试它!

    System.out.println("a:" + a);
    System.out.println("b:" + b);
    swap(a,b);
    System.out.println("a:" + a);
    System.out.println("b:" + b);
于 2017-10-10T21:15:51.063 回答
0

对于整数类型,您可以执行

a ^= b;
b ^= a;
a ^= b;

使用按位异或运算符^。与所有其他建议一样,您可能不应该在生产代码中使用它。

由于我不知道的原因,单行版本a ^= b ^= a ^= b不起作用(也许我的 Java 编译器有错误)。单行在 C 中与我尝试过的所有编译器一起工作。但是,两行版本有效:

a ^= b ^= a;
b ^= a;

b ^= a;
a ^= b ^= a;

证明它有效:设 a₀ 和 b₀ 为a和的初始值b。在第一行之后,a是 a₁ = a₀ xor b₀;在第二行之后,b是 b₁ = b₀ xor a₁ = b₀ xor (a₀ xor b₀) = a₀。在第三行之后,a是 a₂ = a₁ xor b₁ = a₁ xor (b₀ xor a₁) = b₀。

于 2019-10-17T19:28:06.210 回答