Подтвердить что ты не робот

Удалить несколько элементов из ArrayList

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Чтобы удалить элементы в 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);

Ответ 3

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

Ответ 4

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

Ответ 5

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

list.subList(indexStart, indexEnd).clear()

Ответ 6

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

/**
 * 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;
}

Ответ 7

закажите свой список индексов, например

если 2,12,9,7,3 порядка до 12,9,7,3,2

а затем сделайте это

for(var i = 0; i < indexes.length; i++) { source_array.remove(indexes[0]); }

это должно решить вашу проблему.

Ответ 8

Если элементы, которые вы хотите удалить, сгруппированы вместе, вы можете выполнить операцию subList(start, end).clear().

Если элементы, которые вы хотите удалить, разбросаны, может быть лучше создать новый ArrayList, добавить только те элементы, которые вы хотите включить, а затем скопировать обратно в исходный список.

Изменить: я понимаю, что это не вопрос производительности, а логики.

Ответ 9

Вы можете сортировать индексы так много, или вы можете использовать итератор и вызывать remove()

List<String> list = new ArrayList<String>();
    list.add("0");
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    list.add("6");
    List<Integer> indexes = new ArrayList<Integer>();
    indexes.add(2);
    indexes.add(5);
    indexes.add(3);
    int cpt = 0;
    Iterator<String> it = list.iterator(); 
    while(it.hasNext()){
        it.next();
        if(indexes.contains(cpt)){
            it.remove();
        }
        cpt++;
    }

это зависит от того, что вам нужно, но сортировка будет быстрее в большинстве случаев

Ответ 10

Используйте guava! Метод, который вы ищете, - Iterators.removeAll(Iterator removeFrom, Collection elementsToRemove)

Ответ 11

вы можете использовать метод subList с диапазоном индекса, который хотите удалить, и затем наберите clear().

(обратите внимание, что последний параметр исключен, и будут удалены только первый и второй элементы):

public static void main(String[] args) {
    // TODO Auto-generated method stub
    ArrayList<String> animals = new ArrayList<String>();
    animals.add("cow");
    animals.add("dog");
    animals.add("chicken");
    animals.add("cat");
    animals.subList(0, 2).clear();
    for(String s:animals)
        System.out.println(s);
}

}

результат будет: курица кот

Ответ 12

Если вы хотите удалить позиции X в размер

//a is the ArrayList
a=(ArrayList)a.sublist(0,X-1);

Ответ 13

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

for (int i = 0; i < indexes.size(); i++){
   originalArray.remove(indexes.get(i) - i);
}

Ответ 14

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

Ответ 15

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

indices.add(0, i);

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

Ответ 16

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

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

masterList.removeAll(toRemove);