Как отсортировать целочисленный массив в порядке возрастания и убывания, используя лямбду только в Java - PullRequest
0 голосов
/ 10 января 2019
int[] arr2 = new int[] {54, 432, 53, 21, 43};

Я использую это для сортировки, но выдает ошибку.

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

Это также дает ошибку.

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

Ответы [ 6 ]

0 голосов
/ 11 января 2019

С учетом

int[] array = ... ;

Чтобы отсортировать по возрастанию, просто сделайте

Arrays.sort(array);

Вот хороший способ сортировки по убыванию:

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

Это немного медленнее, чем сортировка по возрастанию, а затем обратный массив; он должен сделать дополнительный проход по массиву. Во время выполнения преобладает сортировка массива любого значительного размера, поэтому вряд ли это будет заметно.

Это работает, выполняя побитовое дополнение значений int до и после сортировки. Это обеспечивает точное, без потерь изменение порядка всех возможных значений int. Чтобы увидеть это, вы должны понимать, что Java-интты используют представление two'splement . Подумайте, должны ли ints иметь только три бита. Все значения будут следующими:

         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. Я рекомендую избегать бокса.

0 голосов
/ 10 января 2019

Существуют разные способы создания отсортированного массива int s из несортированного с использованием потоков, как показывают другие ответы. Недостаток этих подходов заключается в том, что требуется либо упаковка / распаковка (чтобы можно было использовать 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.

0 голосов
/ 10 января 2019

Если вам явно нужен собственный лямбда-компаратор, попробуйте это:

    int[] arr2 = new int[] {54,432,53,21,43};
    int[] arr3 = IntStream.of(arr2).boxed().sorted((a, b) -> a - b).mapToInt(Integer::intValue).toArray();
0 голосов
/ 10 января 2019
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())

Благодаря Хольгеру

0 голосов
/ 10 января 2019

Сортировка по возрастанию:

  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();
    
0 голосов
/ 10 января 2019

Вы можете отсортировать ввод типа 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...