Java中数组元素的有效交换

Java中数组元素的有效交换,java,algorithm,swap,Java,Algorithm,Swap,我想知道是否有比这样做更有效的方法来交换数组中的两个元素: String temp = arr[1]; arr[1] = arr[2]; arr[2] = temp; int a = 1; int b = 2; a ^= b; b ^= a; a ^= b; 好吧,这显然不是坏事,甚至是错的,但我需要经常交换,所以我对是否有LIB或其他更有效的方法感兴趣?没有。您可以在每个使用位置使用一个函数使其更加简洁,但最终,所做的工作将是相同的(加上函数调用的开销,直到/除非HotSpot将其内联移动

我想知道是否有比这样做更有效的方法来交换数组中的两个元素:

String temp = arr[1];
arr[1] = arr[2];
arr[2] = temp;
int a = 1; int b = 2; a ^= b; b ^= a; a ^= b;

好吧,这显然不是坏事,甚至是错的,但我需要经常交换,所以我对是否有LIB或其他更有效的方法感兴趣?

没有。您可以在每个使用位置使用一个函数使其更加简洁,但最终,所做的工作将是相同的(加上函数调用的开销,直到/除非HotSpot将其内联移动-为了帮助它实现这一点,请将functon
设为static final
)。

如果您想交换字符串。这已经是实现这一目标的有效方法

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

String temp = arr[1];
arr[1] = arr[2];
arr[2] = temp;
int a = 1; int b = 2; a ^= b; b ^= a; a ^= b;

这将使其无缝:

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);
}
公共静态最终无效交换(T[]a,int i,int j){
T=a[i];
a[i]=a[j];
a[j]=t;
}
公共静态最终无效交换(列表l、int i、int j){
集合。互换(l、i、j);
}
专用无效测试(){
字符串[]a={“你好”,“再见”};
互换(a,0,1);
System.out.println(“a:+Arrays.toString(a));
列表l=新的ArrayList(Arrays.asList(a));
交换(l,0,1);
System.out.println(“l:+l”);
}

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

public static void swap(int[] arr, int i, int j) {
    arr[i] = (arr[i] + arr[j]) - (arr[j] = arr[i]);
}
我从一些原始基准测试中看到,性能差异基本上也可以忽略不计


这是在不使用临时变量(至少对于整数)的情况下交换数组元素的标准方法之一。

非常晚才参加聚会(我很抱歉),但可以实现比这里提供的更通用的解决方案(将同样适用于基元和非基元):

您失去了编译时安全性,但它应该可以做到这一点

注一:如果给定的
数组
null
,则会得到
NullPointerException
;如果给定的
数组
不是数组,则会得到
IllegalArgumentException
;如果任何一个索引对给定的
数组无效,则会得到
ArrayIndexOutOfBoundsException

注二:对于每种数组类型(
Object[]
和所有基元类型)使用单独的方法将更具性能(使用此处给出的其他方法),因为这需要一些装箱/拆箱。但要编写/维护的代码也要多得多。

试试这个:

    int lowIndex = 0;
    int highIndex = elements.length-1;

    while(lowIndex < highIndex) {
        T lowVal = elements[lowIndex];
        T highVal = elements[highIndex];
        elements[lowIndex] = highVal;
        elements[highIndex] = lowVal;

        lowIndex += 1;
        highIndex -=1;
    }
int-lowIndex=0;
int highIndex=elements.length-1;
而(低指数<高指数){
T lowVal=元素[lowIndex];
T highVal=元素[高索引];
元素[低索引]=高值;
元素[高索引]=低值;
低指数+=1;
高指数-=1;
}

使用
集合。交换
数组。asList

Collections.swap(Arrays.asList(arr), i, j);

首先,您不应该为(int k=0;k**对象和基元类型的解决方案编写

public static final <T> void swap(final T[] arr, final int i, final int j) {
    T tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final boolean[] arr, final int i, final int j) {
    boolean tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final byte[] arr, final int i, final int j) {
    byte tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final short[] arr, final int i, final int j) {
    short tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final int[] arr, final int i, final int j) {
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final long[] arr, final int i, final int j) {
    long tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final char[] arr, final int i, final int j) {
    char tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final float[] arr, final int i, final int j) {
    float tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
public static final void swap(final double[] arr, final int i, final int j) {
    double tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
公共静态最终无效交换(最终T[]arr,最终int i,最终int j){
T tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效交换(最终布尔值[]arr,最终整数i,最终整数j){
布尔tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效交换(最终字节[]arr,最终整数i,最终整数j){
字节tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效掉期(最终短期[]arr,最终整数i,最终整数j){
短tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效交换(最终整数[]arr,最终整数i,最终整数j){
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效掉期(最终长[]arr,最终整数i,最终整数j){
长tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效交换(最终字符[]arr,最终整数i,最终整数j){
char tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效掉期(最终浮动[]arr,最终整数i,最终整数j){
浮动tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
公共静态最终无效交换(最终双[]arr,最终整数i,最终整数j){
双tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
}

这只是“黑客”式的方法:

int d[][] = new int[n][n];

static int swap(int a, int b) {
  return a;
}
...

in main class --> 

d[i][j + 1] = swap(d[i][j], d[i][j] = d[i][j + 1])
就地交换(如果您不知道)可以通过不创建临时变量来节省一些空间

arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j];

对于字符串?不,不完全是。如果您需要经常这样做,您最好只滚动您自己的函数一次,然后这不是一个难题。如果您可以使用列表而不是数组,您可以使用Collections.swap(List,i,j).@Sergio Nakanishi:有趣的是,也许我可以切换到集合,但是我不确定纯数组的使用是否会更快?@Robin:我通常更喜欢使用ArrayList而不是数组。ArrayList在内部使用数组,调用方法来操纵数组的开销并不重要。这本书有效的Java有一个选择列表而不是数组的完整推理。@SergioNakanishi谢谢你的书中技巧。我刚用谷歌搜索了一下,它看起来很不错。你用了哪些测试来测试它,速度有哪些提高?@bhuang3-请修改你的帖子,解释为什么Java编译器不执行此优化。我当然怀疑它是d因此,DV.@ DejChern,我不考虑编译器优化…我只是在谈论编程。这是更长的,更混乱,更难阅读和更多的代码行。我认为它更有效,只是关于栈上声明的变量数目的资源,但是没有理由相信OP是在请求。沿着这一资源进行优化,使DV保持不变…@Robin不客气,然而,正如
djechlin
所说,这种方式很难理解,它只是一种编程方式
arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j];