web-dev-qa-db-fra.com

Comment supprimer tous les éléments nuls d'un tableau de tableaux ou de tableaux?

J'essaye avec une boucle comme ca

// ArrayList tourists

for (Tourist t : tourists) {
    if (t != null) {     
        t.setId(idForm); 
    }   
}

Mais ce n'est pas Nice. Quelqu'un peut-il me suggérer une meilleure solution? 


Quelques repères utiles pour prendre de meilleures décisions: 

Test de performances boucle en boucle, boucle for et itérateur

169

Essayer:

tourists.removeAll(Collections.singleton(null));

Lire le API Java . Le code lancera Java.lang.UnsupportedOperationException pour les listes immuables (comme celles créées avec Arrays.asList); voir cette réponse pour plus de détails.

343
Lithium

À partir de 2015, c’est le meilleur moyen (Java 8):

tourists.removeIf(Objects::isNull);

Remarque: Ce code lancera Java.lang.UnsupportedOperationException pour les listes de taille fixe (telles que celles créées avec Arrays.asList), y compris les listes immuables.

95
MarcG
list.removeAll(Collections.singleton(null));

Il lèvera UnsupportedException si vous l'utilisez sur Arrays.asList car il vous donne une copie Immutable afin qu'il ne puisse pas être modifié. Voir ci-dessous le code. Il crée une copie Mutable et ne lève aucune exception.

public static String[] clean(final String[] v) {
    List<String> list = new ArrayList<String>(Arrays.asList(v));
    list.removeAll(Collections.singleton(null));
    return list.toArray(new String[list.size()]);
}
44
AZ_

Pas efficace, mais court

while(tourists.remove(null));
18
Peter Lawrey

Si vous préférez des objets de données immuables, ou si vous ne voulez simplement pas détruire la liste d'entrée, vous pouvez utiliser les prédicats de Guava.

ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))
18
James Kojo
 for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }
7
Mat Mannion

La classe Objects a une nonNullPredicate qui peut être utilisée avec filter.

Par exemple:

tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());
3
JeffF

Avec Java 8, vous pouvez le faire avec stream() et filter().

tourists = tourists.stream().filter(t -> t != null).collect(Collectors.toList())

ou

tourists = tourists.stream().filter(Objects::nonNull).collect(Collectors.toList())

Pour plus d'informations: Java 8 - Streams

3
Jad Chahine

Pré-Java 8, vous devez utiliser:

tourists.removeAll(Collections.singleton(null));

Utilisation post-Java 8:

tourists.removeIf(Objects::isNull);

La raison ici est la complexité du temps. Le problème avec les tableaux est qu'une opération de suppression peut prendre O(n) temps. Vraiment en Java, il s’agit d’une copie de tableau des éléments restants déplacés pour remplacer l’emplacement vide. De nombreuses autres solutions proposées ici vont provoquer ce problème. Le premier est techniquement O (n * m) où m est 1 parce que c'est un singleton null: donc O (n)

Vous devez supprimer Tout le singleton. En interne, il effectue un batchRemove () qui a une position de lecture et une position d’écriture. Et itère la liste. Lorsqu'il atteint une valeur nulle, il itère simplement la position de lecture de 1. Lorsqu'il est identique, il passe, lorsqu'il est différent, il continue à copier les valeurs. Puis, à la fin, la taille est ajustée.

Il le fait effectivement en interne:

public static <E> void removeNulls(ArrayList<E> list) {
    int size = list.size();
    int read = 0;
    int write = 0;
    for (; read < size; read++) {
        E element = list.get(read);
        if (element == null) continue;
        if (read != write) list.set(write, element);
        write++;
    }
    if (write != size) {
        list.subList(write, size).clear();
    }
}

Ce que vous pouvez voir explicitement est une opération O(n).

La seule chose qui pourrait jamais être plus rapide est si vous avez itéré la liste des deux côtés, et lorsque vous avez trouvé un null, vous définissez sa valeur égale à la valeur trouvée à la fin et décrémenté cette valeur. Et itéré jusqu'à ce que les deux valeurs correspondent. Vous feriez foirer l'ordre, mais réduiriez considérablement le nombre de valeurs .__ que vous définissez par rapport à celles que vous avez laissées seules. Ce qui est une bonne méthode à connaître mais qui n’aidera pas beaucoup ici, puisque .set () est fondamentalement gratuit, mais cette forme de suppression est un outil utile pour votre ceinture.


for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }

Bien que cela semble assez raisonnable, le .remove () sur l'itérateur appelle en interne:

ArrayList.this.remove(lastRet);

Ce qui est encore l'opération O(n) dans la suppression. Il fait un System.arraycopy () qui, encore une fois, n’est pas ce que vous voulez, si vous vous souciez de la vitesse. Cela le rend n ^ 2.

Il y a aussi:

while(tourists.remove(null));

Qui est O (m * n ^ 2). Ici, nous ne faisons pas que parcourir la liste. Nous réitérons la liste complète, chaque fois que nous correspondons à la valeur null. Ensuite, nous faisons n/2 opérations (moyennes) pour effectuer System.arraycopy () afin d'effectuer la suppression . Vous pouvez littéralement trier la collection entière entre les éléments avec des valeurs et les éléments avec des valeurs NULL et couper la fin en moins temps. En fait, cela est vrai pour tous les cassés. Au moins en théorie, la copie réelle de system.arraycopy n’est pas réellement une opération N dans la pratique. En théorie, théorie et pratique sont la même chose; en pratique, ils ne le sont pas.

3
Tatarize

Il existe un moyen simple de supprimer toutes les valeurs null de collection.Vous devez transmettre une collection contenant null en tant que paramètre de la méthode removeAll().

List s1=new ArrayList();
s1.add(null);

yourCollection.removeAll(s1);
3
shiv

C'est un moyen facile de supprimer les valeurs nulles par défaut d'arraylist

     tourists.removeAll(Arrays.asList(null));  

sinon, la valeur de chaîne "null" est supprimée de l'arraylist

       tourists.removeAll(Arrays.asList("null"));  
2
Jobin_vibes

J'ai utilisé l'interface de flux avec l'opération de flux collect et une méthode d'assistance pour générer une nouvelle liste.

tourists.stream().filter(this::isNotNull).collect(Collectors.toList());

private <T> boolean isNotNull(final T item) {
    return  item != null;
}
1
Mabi

Nous pouvons utiliser le même itérateur pour supprimer toutes les valeurs nulles.

Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
    if(itr.next() == null){
        itr.remove();
    }
}
1
amit

J'ai joué avec cela et ai découvert que trimToSize () semble fonctionner. Je travaille sur la plate-forme Android, donc ce pourrait être différent.

1
theblitz

Semblable à @Lithium answer mais ne génère pas d'erreur "La liste ne peut pas contenir le type null":

   list.removeAll(Collections.<T>singleton(null));
0
List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);
0
cunhaf

En utilisant Java 8 , cela peut être effectué de différentes manières à l'aide de flux, flux parallèles et méthode removeIf:

List<String> stringList = new ArrayList<>(Arrays.asList(null, "A", "B", null, "C", null));
List<String> listWithoutNulls1 = stringList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
List<String> listWithoutNulls2 = stringList.parallelStream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
stringList.removeIf(Objects::isNull); //[A,B,C]

Le flux parallèle utilisera les processeurs disponibles et accélérera le processus pour obtenir des listes de taille raisonnable. Il est toujours conseillé d'effectuer des tests de performance avant d'utiliser des flux.

0
i_am_zero