Удалить несколько элементов из ArrayList - PullRequest
31 голосов
/ 10 февраля 2011

У меня есть несколько индексов, и я хочу удалить элементы с этими индексами из ArrayList. Я не могу сделать простую последовательность remove() с, потому что элементы смещаются после каждого удаления. Как мне это решить?

Ответы [ 16 ]

38 голосов
/ 10 февраля 2011

Для удаления элементов на indexes:

Collections.sort(indexes, Collections.reverseOrder());
for (int i : indexes)
    strs.remove(i);

Или, используя Stream API из Java 8:

indexes.sort(Comparator.reverseOrder());
indexes.stream().mapToInt(i -> i).forEach(l::remove);
28 голосов
/ 10 февраля 2011

Сортировка индексов в порядке убывания, а затем удаление их по одному.Если вы сделаете это, удаление не повлияет на индексы, которые вы позже захотите удалить.

Способ их сортировки будет зависеть от коллекции, которую вы используете для хранения индексов.Если это список, вы можете сделать это:

List<Integer> indices;
Collections.sort(indices, new Comparator<Integer>() {
   public int compare(Integer a, Integer b) {
      //todo: handle null
      return b.compareTo(a);
   }
}

Редактировать

@ aioobe нашел помощника, которого мне не удалось найти.Вместо вышеперечисленного вы можете использовать

Collections.sort(indices, Collections.reverseOrder());
6 голосов
/ 02 ноября 2014

Я пришел сюда для удаления элементов в определенном диапазоне (т. Е. Всех элементов между 2 индексами) и нашел это:

list.subList(indexStart, indexEnd).clear()
3 голосов
/ 10 февраля 2011

Вы можете удалить индексы в обратном порядке.Если индексы в порядке, как 1,2,3, вы можете сделать removeRange (1, 3).

3 голосов
/ 10 февраля 2011

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

2 голосов
/ 10 февраля 2011

Я думаю, что Нанда был правильным ответом.

List<T> toRemove = new LinkedList<T>();
for (T t : masterList) {
  if (t.shouldRemove()) {
    toRemove.add(t);
  }
}

masterList.removeAll(toRemove);
1 голос
/ 10 февраля 2011

Если у вас действительно много элементов для удаления (и длинный список), может быть быстрее выполнить итерации по списку и добавить все элементы, которые не должны быть удалены, в новый список, поскольку каждый remove() -этап в массив-список копирует все элементы после удаленного по одному. В этом случае, если ваш индексный список еще не отсортирован (и вы можете перебирать его параллельно основному списку), вы можете использовать HashSet или BitSet или некоторую аналогичную O (1) -доступную структуру для contains() проверьте:

/**
 * creates a new List containing all elements of {@code original},
 * apart from those with an index in {@code indices}.
 * Neither the original list nor the indices collection is changed.
 * @return a new list containing only the remaining elements.
 */
public <X> List<X> removeElements(List<X> original, Collection<Integer> indices) {
    // wrap for faster access.
    indices = new HashSet<Integer>(indices);
    List<X> output = new ArrayList<X>();
    int len = original.size();
    for(int i = 0; i < len; i++) {
       if(!indices.contains(i)) {
           output.add(original.get(i));
       }
    }
    return output;
}
0 голосов
/ 19 ноября 2016

Я попал сюда по аналогичному запросу, и ответ @ aioobe помог мне найти решение.Однако, если вы заполняете список индексов для удаления самостоятельно, вы можете рассмотреть возможность использования this :

indices.add(0, i);

Это устранит необходимость (дорогостоящей) обратной сортировкисписок перед итерацией по нему, удаляя элементы из основного ArrayList.

0 голосов
/ 14 ноября 2016

Более эффективный метод, который, как я полагаю, я не видел выше, - это создание нового Arraylist и выбор выживших индексов путем копирования их в новый массив. И, наконец, переназначить ссылку.

0 голосов
/ 06 марта 2016

Если ваш массив indexes отсортирован (например, 1, 3, 19, 29), вы можете сделать это:

for (int i = 0; i < indexes.size(); i++){
   originalArray.remove(indexes.get(i) - i);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...