#java
#java
Вопрос:
Название говорит само за себя. Например
[2, 1, 0, -2, -5]
станет
[-5, -2, 2, 1, 0]
Моя стратегия состоит в том, чтобы сначала отсортировать их в порядке возрастания, затем отсортировать их отдельно по отрицательным и положительным числам, но моя стратегия расплывчата. Я знаю, что это расплывчато, но ваши ответы мне бы очень помогли.
Комментарии:
1. Вы пробовали какое-либо решение, вы должны добавить его?
2. Напишите пользовательский компаратор, который использует Math.abs() внутри.
3. На самом деле это немного сложно сделать чисто, потому что Comparator не будет работать с примитивами. Это обязательно должно быть int[] или это может быть целое число[]?
Ответ №1:
Краткая версия :
Integer[] ary = { 2, 1, 0, -2, -5 };
Arrays.sort(ary, (Integer i1, Integer i2) -> Math.abs(i2) - Math.abs(i1));
System.out.println(Arrays.toString(ary));
Нет необходимости в ArrayList. Однако необходимы целые числа вместо int.
Мой первый ответ был:
Сначала я конвертирую из int[] в List< Integer> и использую лямбда-компаратор, чтобы отсортировать его так, как вы хотите.
int[] ary = { 2, 1, 0, -2, -5 };
List<Integer> intList = new ArrayList<Integer>();
for (int index = 0; index < ary.length; index ) {
intList.add(ary[index]);
}
intList.sort((Integer i1, Integer i2) -> Math.abs(i2) - Math.abs(i1));
System.out.println(intList);
он возвращает
[-5, 2, -2, 1, 0]
Ответ №2:
Это немного запутанно, если вам действительно нужно int[]
.
Вы можете определить компаратор, но поскольку дженерики не работают с примитивами, он не будет работать с int[]
.
Comparator<Integer> integerComparator = (x, y) -> Integer.compare(Math.abs(x), Math.abs(y));
С помощью List<Integer>
и Integer[]
это проще:
List<Integer> integerList = Arrays.asList(2, 1, 0, -2, -5);
Integer[] integerArray = new Integer[] {2, 1, 0, -2, -5};
integerList.sort(integerComparator.reversed());
Arrays.sort(integerArray,integerComparator.reversed());
System.out.println("ints = " integerList);
System.out.println("integerArray = " Arrays.toString(integerArray));
С int[]
это более беспорядочно. Вы можете использовать IntStream
и вставить его с помощью boxed()
в Stream<Integer>
. Но тогда вы получите снижение производительности, но если вы не имеете дело с огромными массивами или не используете их в критической части приложения, это не будет проблемой.
int[]primitiveArray = new int[]{2, 1, 0, -2, -5};
int[] ints = IntStream.of(primitiveArray)
.boxed()
.sorted(integerComparator.reversed())
.mapToInt(Integer::valueOf)
.toArray();
System.out.println("ints = " Arrays.toString(ints));
Комментарии:
1.
Arrays.asList(...)
в этом случае работает, потому что параметры автоматически разделяются на целые числа по отдельности, но если вы это сделаетеArrays.asList(intArray)
, вы получитеList<int[]>
.
Ответ №3:
Это немного объектно-ориентированное решение, которое не требует памяти для копирования массива в список, не требует распаковки списка обратно в массив, и вам не нужно изобретать какие-либо алгоритмы сортировки:
final int[] array = new int[] {2, 1, 0, -2, -5};
Collections.sort(
new AbstractList<Integer>() {
public Integer get(int index) {
return array[index];
}
public int size() {
return array.length;
}
@Override
public Integer set(int index, Integer element) {
int old = array[index];
array[index] = element;
return old;
}
},
new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return Math.abs(o1) - Math.abs(o2);
}
}
);
Если у вас язык Commons, он намного чище:
final int[] array = new int[] {2, 1, 0, -2, -5};
Collections.sort(
ArrayUtils.toObject(array),
new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return Math.abs(o1) - Math.abs(o2);
}
}
);
Компаратор из другого ответа, ((Integer i1, Integer i2) -> Math.abs(i2) - Math.abs(i1))
, — это просто версия lambda, если она приведена здесь. Если у вас Java 8 , не стесняйтесь использовать любой из них.
Комментарии:
1. Однако для каждого сравнения требуется упаковка и распаковка элементов.
2. / машет руками, / бормочет что-то о jit, escape-анализе и о том, как это должно быть быстро когда-нибудь.
Ответ №4:
Просто отсортируйте входные данные comparing(Math::abs, reverseOrder())
:
@Test
public void test() {
List<Integer> input = asList(2, 1, 0, -2, -5);
List<Integer> output = input.stream()
.sorted(comparing(Math::abs, reverseOrder()))
.collect(toList());
System.out.println(output);
}
Выводит
[-5, 2, -2, 1, 0]
Требуется импорт:
import org.junit.Test;
import java.util.List;
import static java.util.Arrays.asList;
import static java.util.Comparator.comparing;
import static java.util.Comparator.reverseOrder;
import static java.util.stream.Collectors.toList;