Переместить определенный элемент в arraylist в последний индекс

#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 и правильный метод to set (подсказка подсказка)

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()));
        }