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 résoudre ce problème?
Triez les index 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 index que vous souhaitez supprimer ultérieurement.
La manière dont vous les triez dépend de la collection que vous utilisez pour stocker les index. Si c'est une liste, vous pouvez faire ceci:
List<Integer> indices;
Collections.sort(indices, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
//todo: handle null
return b.compareTo(a);
}
}
@aioobe a trouvé l'assistant que je n'ai pas trouvé. 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 Stream de Java 8:
indexes.sort(Comparator.reverseOrder());
indexes.stream().mapToInt(i -> i).forEach(l::remove);
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()
Vous pouvez supprimer les éléments en commençant par le plus grand index ou, si vous avez des références aux objets que vous souhaitez supprimer, vous pouvez utiliser la méthode removeAll .
Vous pouvez supprimer les index dans l'ordre inverse. Si les index sont dans l’ordre comme 1,2,3, vous pouvez faire removeRange (1, 3).
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 de parcourir la liste et d'ajouter tous les éléments qui ne doivent pas être supprimés à une nouvelle liste, puisque chaque remove()
- step dans une liste de tableaux est copié. tous les éléments après le supprimer un par un. Dans ce cas, si votre 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 hachage, un bitSet ou une structure similaire O (1) -access-pour le contrôle 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;
}
Utilisez goyave ! La méthode que vous recherchez est Iterators.removeAll (Iterator removeFrom, Collection elementsToRemove)
vous souhaiterez peut-être utiliser la méthode subList avec la plage d'index que vous souhaitez supprimer, puis appelez clear ().
(notez 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: pouletcat
Vous pouvez trier les index 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
En supposant que votre tableau indexes
soit trié (par exemple: 1, 3, 19, 29), vous pouvez le faire:
for (int i = 0; i < indexes.size(); i++){
originalArray.remove(indexes.get(i) - i);
}
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 index à supprimer vous-même, vous pouvez envisager d'utiliser this :
indices.add(0, i);
Cela éliminera le besoin (coûteux) de trier de la liste avant son itération, tout en supprimant des éléments de la liste principale ArrayList.
commandez votre liste d'index, comme ceci
si 2,12,9,7,3 ordre descend à 12,9,7,3,2
et ensuite faire ceci
for(var i = 0; i < indexes.length; i++)
{
source_array.remove(indexes[0]);
}
cela devrait résoudre votre problème.
Une méthode plus efficace que je n'ai pas vue plus haut consiste à créer un nouvel arraylist et à sélectionner les indices qui survivent en les copiant dans le nouveau tableau. Et enfin réaffecter la référence.
Si les éléments que vous souhaitez supprimer sont tous regroupés, vous pouvez effectuer une opération subList(start, end).clear()
.
Si les éléments que vous souhaitez supprimer sont dispersés, il peut être préférable de créer un nouvel ArrayList, d’ajouter uniquement les éléments que vous souhaitez inclure, puis de les copier dans la liste d’origine.
Edit: Je réalise maintenant que ce n’était pas une question de performance mais de logique.
Si vous souhaitez supprimer les positions X à la taille
//a is the ArrayList
a=(ArrayList)a.sublist(0,X-1);