如何在Java中反转int数组?

Mic*_*ott 224 java arrays idioms idiomatic

我试图在Java中反转一个int数组.

此方法不会反转数组.

for(int i = 0; i < validData.length; i++)
{
    int temp = validData[i];
    validData[i] = validData[validData.length - i - 1];
    validData[validData.length - i - 1] = temp;
}
Run Code Online (Sandbox Code Playgroud)

这有什么问题?

Man*_*nur 293

使用Commons.Lang,您可以简单地使用

ArrayUtils.reverse(int[] array)
Run Code Online (Sandbox Code Playgroud)

大多数情况下,当他们处理您的问题时,坚持使用已经过单元测试和用户测试的易于使用的库会更快,更安全.

  • 我的观点不是副本或副本.我的消息指出要返回的"(传递)"(在被反转之后),所以它可以在表达式中传递,而不需要单独的语句. (4认同)
  • 我会优先考虑返回反向(传递)数组,以实现类似功能的样式. (3认同)
  • @ laurent-g是公平的:以这种方式反转数组的内存效率更高,这可能就是他们这样做的原因。 (2认同)

3le*_*gos 272

要反转int数组,您可以交换项目直到达到中点,如下所示:

for(int i = 0; i < validData.length / 2; i++)
{
    int temp = validData[i];
    validData[i] = validData[validData.length - i - 1];
    validData[validData.length - i - 1] = temp;
}
Run Code Online (Sandbox Code Playgroud)

你这样做,你交换每个元素两次,所以结果与初始列表相同.

  • @JinKwon这有点像`validData.length >> 1`.这是等效和更快的,但它让许多程序员感到困惑,任何好的编译器都会自动执行此操作. (9认同)
  • @Jin我不会.它只是混淆了含义,我敢打赌优化编译器无论如何都会为你做这件事.无论如何,只有在您从分析中获得有必要/有帮助的明确证据之后,才能进行微观优化. (6认同)
  • 你应该只对`validData.length - i - 1`进行一次计算并将其保存到变量中. (2认同)
  • @sg28 消除临时变量有什么意义? (2认同)

Tar*_*rik 50

public class ArrayHandle {
    public static Object[] reverse(Object[] arr) {
        List<Object> list = Arrays.asList(arr);
        Collections.reverse(list);
        return list.toArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • int的数组不是对象,这不起作用. (30认同)
  • 当然会的.列表只能保存对象,而不是基元,因此所有基元(在本例中为"int")都包含在各自的包装器中(在本例中为"整数")并放入列表中.你看,'整数是对象.@汤姆 (11认同)
  • 注意:如果我没错,原始数组会被修改.为了说清楚,你可能想要不返回任何东西. (6认同)
  • @Andrea实际上,事实并非如此.`Arrays.asList()`返回的列表不引用原始数组,也不返回数组.这是这种方法的问题之一:它使用三倍的内存,并将工作三倍作为就地算法. (3认同)
  • 这个方法本身可能有效,但是根本不能将`int []`作为参数传递给这个方法(*"不兼容的类型:int []不能转换为Object []"*). (3认同)
  • @ 11684是的,通用列表只能容纳对象.但该方法除了数组.数组可以保存基元.因此`int []`与`Integer []`不同.试一试:`Integer [] array = new int [5]`.你会得到一个编译错误.这就是Java`Arrays`类定义了一堆处理原始数组的方法的原因.试图将`int []`传递给上面的方法将导致类似MakeSimple类型中的方法reverse(Object [])不适用于参数(int [])`.@Filip - 就地算法使用更少的内存并运行得更快. (2认同)

Bil*_*ard 39

如果你声明显式变量来跟踪你在循环的每次迭代中交换的索引,我认为遵循算法的逻辑会更容易一些.

public static void reverse(int[] data) {
    for (int left = 0, right = data.length - 1; left < right; left++, right--) {
        // swap the values at the left and right indices
        int temp = data[left];
        data[left]  = data[right];
        data[right] = temp;
    }
}
Run Code Online (Sandbox Code Playgroud)

我也认为在while循环中执行此操作更具可读性.

public static void reverse(int[] data) {
    int left = 0;
    int right = data.length - 1;

    while( left < right ) {
        // swap the values at the left and right indices
        int temp = data[left];
        data[left] = data[right];
        data[right] = temp;

        // move the left and right index pointers in toward the center
        left++;
        right--;
    }
}
Run Code Online (Sandbox Code Playgroud)


esc*_*ram 39

Collections.reverse(Arrays.asList(yourArray));
Run Code Online (Sandbox Code Playgroud)

java.util.Collections.reverse()可以反转java.util.Lists并java.util.Arrays.asList()返回一个包含您传递给它的特定数组的列表,因此yourArray在调用之后会反转Collections.reverse().

成本只是创建一个List对象,不需要额外的库.

在Tar​​ik及其评论员的回答中提出了类似的解决方案,但我认为这个答案会更简洁,更容易解析.

  • 对于对象数组,这是一个很好的解决方案.但它不适用于基元数组.E. g.将`int []`传递给`asList(...)`不会返回`List <Integer>`,而是返回一个包含一个元素的`List <int []>`.AFAICS没有简单的内置方法将`int []`转换为`Integer []`. (14认同)
  • 这将不适用于原始数组...集合dosnt返回一个值,因此现在您有了一个无用的数组作为内存中的列表 (2认同)

Pat*_*ker 12

这里已经有很多答案,主要集中在就地修改数组.但是为了完整起见,这是使用Java流来保留原始数组并创建新的反向数组的另一种方法:

    int[] a = {8, 6, 7, 5, 3, 0, 9};
    int[] b = IntStream.rangeClosed(1, a.length).map(i -> a[a.length-i]).toArray();
Run Code Online (Sandbox Code Playgroud)


Zhe*_*lov 10

与番石榴:

Collections.reverse(Ints.asList(array));
Run Code Online (Sandbox Code Playgroud)

  • 这太棒了!简短有效.像所有`asList`方法一样,它创建了一个**视图**,它直接写入后备(原始)数组.我认为这里的选民错误地认为这会返回一个盒装清单或其他东西. (4认同)
  • @AnthonyJClink不确定"它"是指什么,但JDK实用程序`Collections.reverse`是一个void方法.它在一个包含`int []`的Guava内部类上就地操作(因为它从不存储盒装的`Integer的列表,我不会将该类称为"盒装列表",而是"列表视图"一个数组").但是它是通过传递`Integer`对象的接口来操作的,所以这会产生很多临时对象流失和拳击.尝试使用`IntStream`或原始集合库来处理性能问题.(Trove,Koloboke,Eclipse Collections,......) (2认同)

Ape*_*nut 7

简单的循环!

for (int start = 0, end = array.length - 1; start <= end; start++, end--) {
    int aux = array[start];
    array[start]=array[end];
    array[end]=aux;
}
Run Code Online (Sandbox Code Playgroud)

  • 在将来,请让提问者明确知道他们做错了什么,以及你做了什么. (4认同)

Ant*_*ink 6

这就是我个人将如何解决它。创建参数化方法背后的原因是允许对任何数组进行排序……而不仅仅是您的整数。

我希望你能从中有所收获。

@Test
public void reverseTest(){
   Integer[] ints = { 1, 2, 3, 4 };
   Integer[] reversedInts = reverse(ints);

   assert ints[0].equals(reversedInts[3]);
   assert ints[1].equals(reversedInts[2]);
   assert ints[2].equals(reversedInts[1]);
   assert ints[3].equals(reversedInts[0]);

   reverseInPlace(reversedInts);
   assert ints[0].equals(reversedInts[0]);
}

@SuppressWarnings("unchecked")
private static <T> T[] reverse(T[] array) {
    if (array == null) {
        return (T[]) new ArrayList<T>().toArray();
    }
    List<T> copyOfArray = Arrays.asList(Arrays.copyOf(array, array.length));
    Collections.reverse(copyOfArray);
    return copyOfArray.toArray(array);
}

private static <T> T[] reverseInPlace(T[] array) {
    if(array == null) {
        // didn't want two unchecked suppressions
        return reverse(array);
    }

    Collections.reverse(Arrays.asList(array));
    return array;
}
Run Code Online (Sandbox Code Playgroud)

  • 不解决使用原始问题的原始问题。 (2认同)
  • 您实际上不需要复制数组,只需`Collections.reverse(asList(arraytoReverse)); 返回 arrayToReverse;`。`asList` 只是数组的包装器,因此原始数组被反转。 (2认同)

小智 5

如果使用更原始的数据(即 char、byte、int 等),那么您可以执行一些有趣的 XOR 操作。

public static void reverseArray4(int[] array) {
    int len = array.length;
    for (int i = 0; i < len/2; i++) {
        array[i] = array[i] ^ array[len - i  - 1];
        array[len - i  - 1] = array[i] ^ array[len - i  - 1];
        array[i] = array[i] ^ array[len - i  - 1];
    }
}
Run Code Online (Sandbox Code Playgroud)


Kri*_*iya 5

这会对你有所帮助

int a[] = {1,2,3,4,5};
for (int k = 0; k < a.length/2; k++) {
    int temp = a[k];
    a[k] = a[a.length-(1+k)];
    a[a.length-(1+k)] = temp;
}
Run Code Online (Sandbox Code Playgroud)


Dee*_*ngh 5

for(int i=validData.length-1; i>=0; i--){
  System.out.println(validData[i]);
 }
Run Code Online (Sandbox Code Playgroud)

  • 这对于获取数组的值很有用,但如果您确实想反转数组,则必须使用此方法创建一个新数组=&gt;其他数组会更有效。 (3认同)

i_a*_*ero 5

对于Java 8,我们还可以使用流将整数数组反转为:

int[] sample = new int[]{1,2,3,4,5};
int size = sample.length;
int[] reverseSample = IntStream.range(0,size).map(i -> sample[size-i-1])
                      .toArray(); //Output: [5, 4, 3, 2, 1]
Run Code Online (Sandbox Code Playgroud)


Kar*_*nna 5

有两种方法可以解决该问题:

1. 反转空间中的数组。

步骤 1. 交换起始索引和结束索引处的元素。

步骤 2. 增加起始索引并减少结束索引。

步骤 3. 迭代步骤 1 和步骤 2,直到开始索引 < 结束索引

为此,时间复杂度为 O(n),空间复杂度为 O(1)

在空间中反转数组的示例代码如下:

public static int[] reverseAnArrayInSpace(int[] array) {
    int startIndex = 0;
    int endIndex = array.length - 1;
    while(startIndex < endIndex) {
        int temp = array[endIndex];
        array[endIndex] = array[startIndex];
        array[startIndex] = temp;
        startIndex++;
        endIndex--;
    }
    return array;
}
Run Code Online (Sandbox Code Playgroud)

2. 使用辅助数组反转数组。

步骤 1. 创建一个大小等于给定数组的新数组。

步骤 2. 从给定数组的结束索引开始,将元素插入到新数组中。

为此,时间复杂度为 O(n),空间复杂度为 O(n)

使用辅助数组反转数组的示例代码如下:

public static int[] reverseAnArrayWithAuxiliaryArray(int[] array) {
    int[] reversedArray = new int[array.length];
    for(int index = 0; index < array.length; index++) {
        reversedArray[index] = array[array.length - index -1]; 
    }
    return reversedArray;
}
Run Code Online (Sandbox Code Playgroud)

另外,我们可以使用 Java 的 Collections API 来完成此操作。

Collections API 内部使用相同的反向空间方法。

使用 Collections API 的示例代码如下:

public static Integer[] reverseAnArrayWithCollections(Integer[] array) {
    List<Integer> arrayList = Arrays.asList(array);
    Collections.reverse(arrayList);
    return arrayList.toArray(array);
}
Run Code Online (Sandbox Code Playgroud)