#java
#java
Вопрос:
Допустим, у меня есть этот список
List<Integer> grades = Arrays.asList(9,8,1,0,7,0,0,3);
Я хочу переместить все нули в последние индексы .. Поэтому я хочу, чтобы результат был примерно таким:
9,8,1,7,3,0,0,0
Я могу сделать это с помощью простых массивов, но я все еще не понял, как это сделать в ArrayList.
Комментарии:
1. «Я могу сделать это с помощью простых массивов» это в основном то же самое, просто используйте правильный метод to
get
и правильный метод toset
(подсказка подсказка)2. Список<Целое число> цена = Arrays.asList(9,8,1,0,7,0,0,3); int count = 0; for(int i=0; i(i)); } } в то время как(количество toArray())); }
Ответ №1:
Вы можете отсортировать список соответствующим образом, используя Comparator.comparing, чтобы переместить все 0
в последнее, а не сортировать оставшиеся значения
grades.sort(Comparator.comparing(value -> value == 0 ? 1 /* sort last */ : 0 /* don't sort */)); //[9, 8, 1, 7, 3, 0, 0, 0]
Комментарии:
1. Семантика вашего экстрактора не сразу очевидна, и я бы запросил комментарий (или, что еще лучше, именованную константу), если бы увидел это в code review.
2. извините, что вы называете меня
i
собственным именем? не могли бы вы уточнить свой комментарий? @chrylis-осторожно оптимистично-3. Я думаю, что использование
i
может ввести в заблуждение, поскольку обычно это имя переменной индекса . Возможно, использованиеvalue
или сокращениеv
сделает логику более понятной. Возможно, вы также могли бы добавить комментарии, хотя я думаю, что это излишне, напримерcomparing(value -> value == 0 ? 1/*sort last*/ : 0/*sort first*/)
. На мой взгляд, создание констант для значений 1 и 0 определенно излишне, поэтому я не согласен с chrylis в этом.4.Придирка к стилю кода:
value->value
выглядит как ссылка на указатель C (оператор со стрелкой). Пожалуйста, используйте пробелы вокруг операторов, особенно этого, т. е.value -> value == 0
5. @chrylis-осторожно оптимистично — цель — «последние нули», поэтому мне было интересно, не неправильно ли вы назвали функцию, но на самом деле вы перевернули 0 и 1, так что… Сбивает с толку …
Ответ №2:
Как отмечалось в комментариях, вы можете повторно использовать тот же код, который у вас есть для массивов, используя методы List
‘s get
и set
вместо []
оператора.
Другим «хитрым» подходом может быть использование того факта, что сортировка сохраняет относительные позиции двух эквивалентных элементов, и сортировка списка с помощью пользовательского параметра, Comparator
который сортирует в зависимости от того, равен элемент или нет 0
— все нули будут перемещены в конец, а все остальные элементы будут сохраненыих относительные позиции:
grades.sort(Comparator.comparing(i -> i == 0));
Комментарии:
1. Это зависит от неочевидной детали, которая
TRUE
считается большей и, следовательно, сортируется позже, чем,FALSE
.2. @chrylis-осторожно оптимистично — Хорошо документировано , что естественный порядок
Boolean
сортировкиfalse
раньшеtrue
.3. @Andreas Это, безусловно, задокументировано. Этот бесспорно умный трюк преобразования нулевого значения в предикат и сортировки по нему достаточно умен, чтобы потребовать объяснения.
4. @chrylis-осторожно оптимистично — Согласен. В этом случае хитрость (очень хорошая, с моей стороны) , вероятно, поставит в тупик большинство людей, по крайней мере, на некоторое время, поэтому такой комментарий может быть хорошим:
// sorts 0's last, since true sorts last
Ответ №3:
Для более быстрой реализации O (n), чем при использовании решения O (n log (n)) sort()
, сделайте это так же, как вы бы сделали это для массива:
int j = 0;
for (Integer value : grades) {
if (value != 0) {
grades.set(j , value);
}
}
while (j < grades.size()) {
grades.set(j , 0);
}
Конечно, использование set(int, ?)
может плохо сказаться на производительности, если не an ArrayList
, поэтому было бы лучше использовать обновляемый итератор, то есть a ListIterator
:
ListIterator<Integer> iter = grades.listIterator();
for (Integer value : grades) {
if (value != 0) {
iter.next(); // No need to call hasNext() first
iter.set(value);
}
}
while (iter.hasNext()) {
iter.next();
iter.set(0);
}
Для сравнения, вот сопоставимое решение для массива:
int[] grades = {9,8,1,0,7,0,0,3};
int j = 0;
for (int i = 0; i < grades.length; i ) {
if (grades[i] != 0) {
grades[j ] = grades[i];
}
}
while (j < grades.length) {
grades[j ] = 0;
}
Ответ №4:
Спасибо, ребята..
Мне удалось сделать это так же, как я делал это с простыми массивами :
List<Integer> price = Arrays.asList(9,8,1,0,7,0,0,3);
int count = 0;
for(int i=0; i<price.size(); i ) {
if(price.get(i) !=0) {
price.set(count , price.get(i));
}
}
while(count<price.size()) {
price.set(count , 0);
}
System.out.print(Arrays.toString(price.toArray()));
}