繁体   English   中英

如何在java中仅使用lambda按升序和降序对整数数组进行排序

[英]How to sort integer array in ascending and descending order using lambda only in java

int[] arr2 = new int[] {54, 432, 53, 21, 43};

我正在使用它来排序,但它给出了一个错误。

Arrays.sort(arr2, (a, b) -> a - b);

这也是一个错误。

arr2.sort((a, b) -> a - b);

您可以将Integer[]类型的输入排序为:

Integer[] arr2 = new Integer[] {54,432,53,21,43};
Arrays.sort(arr2, Comparator.reverseOrder());

或者可能与原始类型:

int[] arr2 = new int[]{54, 432, 53, 21, 43};
int[] sortedArray = Arrays.stream(arr2)
        .boxed()
        .sorted(Comparator.reverseOrder()) // just use 'sorted()' for ascending order
        .mapToInt(Integer::intValue)
        .toArray();

或者进一步使用其中一个现有答案的技巧(请注意尽管应该谨慎使用边界值):

int[] sortedArray = Arrays.stream(arr2)
        .map(i -> -i).sorted().map(i -> -i) // just use 'sorted()' for ascending order
// Edit - use map(i -> ~i).sorted().map(i -> ~i) to be safe from the issue with Integer.MIN_VALUE
        .toArray();

编辑 :对于就地升序排序,您只需执行:

int[] arr2 = new int[]{54, 432, 53, 21, 43};
Arrays.sort(arr2);

特定

int[] array = ... ;

要升序排序,只需这样做

Arrays.sort(array);

这是一种排序降序的好方法:

Arrays.setAll(array, i -> ~array[i]);
Arrays.sort(array);
Arrays.setAll(array, i -> ~array[i]);

这比排序升序然后反转阵列要慢一点; 它必须对数组进行额外的传递。 运行时主要是对任何大小的数组进行排序,因此它不太可能引人注意。

这通过在排序之前和之后对int值进行逐位补充来实现。 这提供了对每个可能的int值的排序的精确,无损的反转。 要看到这一点,您必须了解Java int使用两个补码表示。 考虑一下int是否只有三位。 所有值都如下:

         100  101  110  111  000  001  010  011
          -4   -3   -2   -1   0    1    2    3
MIN_VALUE ^

按位补码运算符~反转每一位。 您可以通过检查看到这反映了关于-1和0之间的轴心点的表格,因此-4变为3,-3变为2,等等。另外,另一个补码将恢复原始值。 因此,对补充值的升序排序是对原始值的降序排序。

请注意,这与否定不同-这在这里做得不对。 它反映了零表,所以零否定为零,-1的否定是1,等等,这是不对称的,因为MIN_VALUE的否定是MIN_VALUE。 因此,在尝试执行降序排序时使用否定不起作用。

最后,装箱和使用Comparator工作,但速度相当慢,并为(几乎)每个int值分配一个单独的对象。 我建议避免拳击。

按升序排序:

  1.  int[] ascArr = Arrays.stream(arr2).boxed().sorted(Comparator.naturalOrder()) .mapToInt(Integer::intValue).toArray(); 
  2.  int[] ascArr = IntStream.of(arr2).boxed().sorted((a, b) -> Integer.compare(a, b)) .mapToInt(Integer::intValue).toArray(); 
  3. int[] ascArr = Arrays.stream(arr2).sorted().toArray();


按降序排序:

  1.  int[] descArr = Arrays.stream(arr2).boxed().sorted(Comparator.reverseOrder()) .mapToInt(Integer::intValue).toArray(); 
  2.  int[] descArr = IntStream.of(arr2).boxed().sorted((a, b) -> Integer.compare(b, a)) .mapToInt(Integer::intValue).toArray(); 

正如其他答案所示,有不同的方法可以使用流从未排序的int创建排序的int数组。 这些方法的缺点是需要装箱/拆箱(以便可以使用Comparator<Integer> ),或者需要新的阵列来容纳这些元素。

这是一种在没有装箱/拆箱的情况下就地排序的方法。 首先,按升序排列:

int[] arr2 = ...
Arrays.sort(arr2);

不幸的是,没有办法使用单行操作按降序排列就地。 您需要先升序,然后反转数组:

int[] arr2 = ...
Arrays.sort(arr2);

int size = arr2.length;
for (int left = 0; left < size / 2; left++) {
    int right = size - i - 1;
    int temp = arr2[right];
    arr2[right] = arr2[left];
    arr2[left] = temp;
}

编辑:正如@Holger在评论中指出的那样,上面的for循环可以改进如下:

for (int left = 0, right = arr2.length - 1; left < right; left++, right--) {
    int temp = arr2[right];
    arr2[right] = arr2[left];
    arr2[left] = temp;
}

另一种方法是按升序排序,然后将元素按相反顺序放入新数组中:

int[] arr2 = ...
Arrays.sort(arr2);

int size = arr2.length;
int[] reversed = new int[size];
Arrays.setAll(reversed, i -> arr2[size - i - 1]);

这使用Arrays.setAll来完成任务。

public class lambdaTest {

    public static void main(String[] args) {
        int[] arr2 = new int[] {54,432,53,21,43};

        int[] sorted = IntStream.of(arr2)
                .boxed()
                .sorted(Comparator.reverseOrder())
                .mapToInt(i -> i)
                .toArray();
        System.out.println("In decending Order:");
        for(int ss : sorted)
        {
            System.out.print(ss+", ");
        }
        System.out.println();
        int[] reversed = IntStream.range(0, sorted.length)
                .map(i -> sorted[sorted.length-i-1])
                .toArray();
        System.out.println("In Ascending Order: ");

        for(int ss1 : reversed)
        {
            System.out.print(ss1+", ");
        }
    }

}

OUTPUT

按降序排列:

432,54,53,43,21,

在升序中:

21,43,53,54,432,

编辑:按自然顺序排序要简单得多(IntStream.of(arr2) .sorted() .toArray())

感谢Holger

如果您明确需要自定义比较器lambda,请尝试以下方法:

    int[] arr2 = new int[] {54,432,53,21,43};
    int[] arr3 = IntStream.of(arr2).boxed().sorted((a, b) -> a - b).mapToInt(Integer::intValue).toArray();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM