Supprimer plusieurs éléments de ArrayList
J'ai un tas d'index et je veux supprimer des éléments à ces index d'un ArrayList
. Je ne peux pas faire une simple séquence de remove()
s car les éléments sont décalés après chaque suppression. Comment puis-je résoudre ce problème?
16 réponses
Triez les indices par ordre décroissant, puis supprimez-les un par un. Si vous faites cela, il n'y a aucun moyen qu'une suppression affecte les indices que vous souhaitez supprimer plus tard.
Comment vous les trier dépendra de la collection que vous utilisez pour stocker les indices. Si c'est une liste, vous pouvez le faire:
List<Integer> indices;
Collections.sort(indices, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
//todo: handle null
return b.compareTo(a);
}
}
Modifier
@aioobe a trouvé l'assistant que j'ai échoué à trouver. Au lieu de ce qui précède, vous pouvez utiliser
Collections.sort(indices, Collections.reverseOrder());
Pour supprimer des éléments à indexes
:
Collections.sort(indexes, Collections.reverseOrder());
for (int i : indexes)
strs.remove(i);
Ou, en utilisant L'API de flux de Java 8:
indexes.sort(Comparator.reverseOrder());
indexes.stream().mapToInt(i -> i).forEach(l::remove);
Vous pouvez supprimer les éléments à partir du plus grand index vers le bas, ou si vous avez des références aux objets que vous souhaitez supprimer, vous pouvez utiliser la méthoderemoveAll .
Vous pouvez supprimer les index dans l'ordre inverse. Si les indices sont dans l'ordre comme 1,2,3 vous pouvez faire removeRange(1, 3).
Je suis venu ici pour supprimer des éléments dans une plage spécifique (c'est-à-dire tous les éléments entre 2 Index), et j'ai trouvé ceci:
list.subList(indexStart, indexEnd).clear()
Je pense que nanda était la bonne réponse.
List<T> toRemove = new LinkedList<T>();
for (T t : masterList) {
if (t.shouldRemove()) {
toRemove.add(t);
}
}
masterList.removeAll(toRemove);
Si vous avez vraiment beaucoup d'éléments à supprimer (et une longue liste), il peut être plus rapide d'itérer sur la liste et d'ajouter tous les éléments qui ne doivent pas être supprimés à une nouvelle liste, puisque chaque remove()
-étape dans une liste de tableau copie tous les éléments après le supprimé un par un. Dans ce cas, si la liste d'index n'est pas déjà triée (et que vous pouvez la parcourir parallèlement à la liste principale), vous pouvez utiliser un HashSet ou un BitSet ou une structure O(1)-access similaire pour la vérification 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;
}
Commandez votre liste d'index, comme ceci
Si 2,12,9,7,3 ordre desc à 12,9,7,3,2
Et puis faites ceci
for(var i = 0; i < indexes.length; i++)
{
source_array.remove(indexes[0]);
}
Cela devrait résoudre votre problème.
, Si les éléments que vous souhaitez supprimer sont tous regroupés, vous pouvez faire un subList(start, end).clear()
opération.
Si les éléments que vous souhaitez supprimer sont dispersés, il peut être préférable de créer une nouvelle ArrayList, ajouter uniquement les éléments que vous souhaitez inclure, puis recopier dans la liste d'origine.
Edit: je me rends compte maintenant que ce n'était pas une question de performance mais de logique.
Vous pouvez trier les indices comme beaucoup l'ont dit, ou vous pouvez utiliser un itérateur et appeler 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++;
}
Cela dépend de ce dont vous avez besoin, mais le tri sera plus rapide dans la plupart des cas
Vous pouvez utiliser la méthode de sous-liste avec la plage d'index que vous souhaitez supprimer et ensuite, appelez clear () dessus.
(Faites attention que le dernier paramètre est exclu et que seuls les premier et deuxième éléments seront supprimés):
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);
}
}
Le résultat sera: poulet chat
Si vous voulez supprimer les positions X à la taille
//a is the ArrayList
a=(ArrayList)a.sublist(0,X-1);
En Supposant que votre indexes
tableau est trié (par exemple: 1, 3, 19, 29), vous pouvez faire ceci:
for (int i = 0; i < indexes.size(); i++){
originalArray.remove(indexes.get(i) - i);
}
Une méthode plus efficace que je suppose que je n'ai pas Vue ci-dessus crée une nouvelle Arraylist et sélectionne les indices qui survivent en les copiant dans le nouveau tableau. Et enfin réaffecter la référence.
Je me suis retrouvé ici pour une requête similaire et la réponse de @aioobe m'a aidé à trouver la solution. Cependant, si vous remplissez la liste des indices à supprimer vous-même, vous pouvez envisager d'utiliser this :
indices.add(0, i);
Cela éliminera le besoin de (le coûteux) tri inverse de la liste avant d'itérer dessus, tout en supprimant des éléments de L'ArrayList principale.