在Java中有效地交换数组元素

Rob*_*bin 45 java

我想知道是否有一种更有效的方式在数组中交换两个元素,而不是像这样做:

String temp = arr[1];
arr[1] = arr[2];
arr[2] = temp;
Run Code Online (Sandbox Code Playgroud)

嗯,这显然是坏事,甚至是错误的,但我需要经常交换所以我感兴趣,如果有任何Libs或提供更有效的方法来做到这一点?

Old*_*eon 32

这应该使它无缝:

public static final <T> void swap (T[] a, int i, int j) {
  T t = a[i];
  a[i] = a[j];
  a[j] = t;
}

public static final <T> void swap (List<T> l, int i, int j) {
  Collections.<T>swap(l, i, j);
}

private void test() {
  String [] a = {"Hello", "Goodbye"};
  swap(a, 0, 1);
  System.out.println("a:"+Arrays.toString(a));
  List<String> l = new ArrayList<String>(Arrays.asList(a));
  swap(l, 0, 1);
  System.out.println("l:"+l);
}
Run Code Online (Sandbox Code Playgroud)

  • 这很有效,谢谢.请注意,这需要一个对象数组,所以如果你继续使用那些奇怪的编译时错误,请确保使用`Integer [] array`而不是`int [] array`. (2认同)

T.J*_*der 25

不.您可以使用一个函数使每个使用它的地方更简洁,但最后,完成的工作将是相同的(加上函数调用的开销,直到/除非HotSpot将其内联移动 - 以帮助它,做功能static final).

  • @Robin:`static`告诉编译器和VM(记住,HotSpot是VM,它进行了大量的运行时优化),它不用担心设置`this`,这样可以更容易内联函数.`final`表示它不会在子类中被覆盖.关于HotSpot对其中任何一个的关注程度,我很容易就错了,真的,我不是热衷于使用HotSpot的最新魔法.:-) (6认同)
  • 仅仅为了记录,使用`static final`而不仅仅是`static`甚至没有?有什么好处? (2认同)
  • 我认为你无法覆盖静态方法. (2认同)
  • @Robin:加载类时加载类中的所有方法,无论是实例还是静态,更多内容在[JLS的第12.4节]中(http://docs.oracle.com/javase/specs/jls/se7/html /jls-12.html#jls-12.4). (2认同)
  • @Sergio:*“我认为您不能覆盖静态方法。” *可以,除非它是`final`,但它与覆盖实例方法有很大不同。请注意,此错误会覆盖`static final`(http://ideone.com/NuMyv4):“错误:Derived中的foo()无法覆盖Base中的foo()...覆盖的方法是静态的,最终的”。如果不是final,该错误就会消失(http://ideone.com/vnuAk6)。仅当您通过*实例引用*调用静态方法时,它才起作用,这很奇怪。所调用的方法是在编译时根据ref的类型确定的:http://ideone.com/yXDgpa。 (2认同)
  • 从技术上讲,子类中的静态方法不会被重写。它们是隐藏的。 (2认同)

bhu*_*ng3 10

如果要交换字符串.它已经是有效的方法.

但是,如果要交换整数,可以使用XOR更有效地交换两个整数,如下所示:

int a = 1; int b = 2; a ^= b; b ^= a; a ^= b;
Run Code Online (Sandbox Code Playgroud)

  • 您使用了哪些测试来对此进行基准测试以及速度改进是什么? (2认同)
  • 它更长、更混乱、更难阅读并且需要更多代码行。我认为仅就堆栈上声明的变量数量资源而言,它的效率更高,但没有理由相信OP要求对该资源进行优化,因此DV代表...... (2认同)
  • @Robin你是受欢迎的,但正如`djechlin`所说,这种方式很难理解读取,这只是一个编程很棘手,顺便说一句,如果两个整数指向同一个地址,它可能会有一些问题但是在java中,内存分配是由JVM处理的,所以很难说这种方式是否实用. (2认同)

kme*_*cpp 9

如果您正在交换数字并希望以简洁的方式编写代码而不创建单独的函数或使用令人困惑的XOR黑客,我发现这更容易理解,它也是一个单行.

public static void swap(int[] arr, int i, int j) {
    arr[i] = (arr[i] + arr[j]) - (arr[j] = arr[i]);
}
Run Code Online (Sandbox Code Playgroud)

我从一些原始基准测试中看到的是,性能差异基本上可以忽略不计.

  • 但是 arr[i] + arr[j] 可能会溢出 (2认同)
  • @ChaojunZhong 这应该不是问题。当减去另一个数字时,新的“[i]”将被很好地计算。在 IDE 中尝试 (2认同)

Zhe*_*lov 6

使用Collections.swapArrays.asList

Collections.swap(Arrays.asList(arr), i, j);
Run Code Online (Sandbox Code Playgroud)

  • 如果数组中的类型是原始类型,这将不起作用。Arrays.asList(int[]) 会将其转换为 int[] 的列表。 (8认同)

Nee*_*lex 5

就地交换(如果您已经不知道)可以通过不创建临时变量来节省一些空间。

arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j];
Run Code Online (Sandbox Code Playgroud)