Como remover todos os elementos nulos de uma ArrayList ou String Array?

Eu tento com um loop assim

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

Mas não é legal. Alguém pode me sugerir uma solução melhor?


Alguns benchmarks úteis para tomar uma decisão melhor:

While loop, loop For e Iterator Performance Test

Experimentar:

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

Leia a API do Java . O código lançará java.lang.UnsupportedOperationException para listas imutáveis ​​(como criadas com Arrays.asList ); veja esta resposta para mais detalhes.

A partir de 2015, esta é a melhor maneira (Java 8):

 tourists.removeIf(Objects::isNull); 

Nota: Este código lançará java.lang.UnsupportedOperationException para listas de tamanho fixo (como criadas com Arrays.asList), incluindo listas imutáveis.

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

Ele lançará UnsupportedException se você usá-lo no Arrays.asList porque ele lhe fornece uma cópia imutável para que ele não possa ser modificado. Veja abaixo o código. Ele cria uma cópia mutável e não lançará nenhuma exceção.

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

Não é eficiente, mas curto

 while(tourists.remove(null)); 

Se você preferir objects de dados imutáveis, ou se você não quer ser destrutivo para a lista de input, você pode usar os predicados de Guava.

 ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull())) 
  for (Iterator itr = tourists.iterator(); itr.hasNext();) { if (itr.next() == null) { itr.remove(); } } 

Existe uma maneira fácil de remover todos os valores null da collection . Você tem que passar uma coleção contendo null como um parâmetro para o método removeAll()

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

A class Objects tem um Predicate nonNull que pode ser usado com o filter .

Por exemplo:

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

Usando o Java 8, você pode fazer isso usando stream() e filter()

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

ou

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

Para mais informações: Java 8 – Streams

Esta é uma maneira fácil de remover valores nulos padrão do arraylist

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

caso contrário, o valor String “null” remove from arraylist

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

Eu brinquei com isso e descobri que trimToSize () parece funcionar. Eu estou trabalhando na plataforma Android, então pode ser diferente.

Podemos usar o iterador para o mesmo para remover todos os valores nulos.

 Iterator itr= tourists.iterator(); while(itr.hasNext()){ if(itr.next() == null){ itr.remove(); } } 

Eu usei a interface de stream junto com a coleta de operação de stream e um método auxiliar para gerar uma nova lista.

 tourists.stream().filter(this::isNotNull).collect(Collectors.toList()); private  boolean isNotNull(final T item) { return item != null; } 

Pré-Java 8 você deve usar:

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

Uso pós-Java 8:

 tourists.removeIf(Objects::isNull); 

A razão aqui é a complexidade do tempo. O problema com as matrizes é que uma operação de remoção pode levar O (n) tempo para ser concluída. Realmente em Java, esta é uma cópia da matriz dos elementos restantes sendo movidos para replace o ponto vazio. Muitas outras soluções oferecidas aqui acionarão esse problema. O primeiro é tecnicamente O (n * m) onde m é 1 porque é um singleton null: so O (n)

Você deve remover All do singleton, internamente ele faz um batchRemove () que tem uma posição de leitura e uma posição de gravação. E repete a lista. Quando atinge um nulo, simplesmente itera a posição de leitura por 1. Quando eles são os mesmos, quando são diferentes, ele continua se movendo copiando os valores. Então, no final, reduz o tamanho.

Isso efetivamente faz isso internamente:

 public static  void removeNulls(ArrayList 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(); } } 

O que você pode ver explicitamente é uma operação O (n).

A única coisa que poderia ser mais rápida seria se você iterasse a lista de ambas as extremidades e, quando encontrasse um nulo, definisse seu valor como igual ao valor encontrado no final e diminuísse esse valor. E iterado até que os dois valores correspondam. Você estragaria o pedido, mas reduziria enormemente o número de valores que definiu e os que você deixou em paz. Que é um bom método para saber, mas não vai ajudar muito aqui como .set () é basicamente gratuito, mas essa forma de exclusão é uma ferramenta útil para o seu cinto.


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

Embora isso pareça razoável o suficiente, o .remove () no iterador chama internamente:

 ArrayList.this.remove(lastRet); 

Qual é novamente a operação O (n) dentro da remoção. Ele faz um System.arraycopy () que não é o que você quer, se você se importa com a velocidade. Isso faz com que seja n ^ 2.

Há também:

 while(tourists.remove(null)); 

Qual é O (m * n ^ 2). Aqui nós não apenas repetimos a lista. Reiteramos toda a lista, toda vez que combinamos com o nulo. Em seguida, fazemos operações n / 2 (média) para fazer o System.arraycopy () para executar a remoção. Você poderia, literalmente, classificar toda a coleção entre itens com valores e itens com valores nulos e aparar a finalização em menos tempo. De fato, isso é verdade para todos os quebrados. Pelo menos em teoria, o atual system.arraycopy não é realmente uma operação N na prática. Teoricamente, teoria e prática são a mesma coisa; na prática eles não são.

Usando o Java 8 isso pode ser feito de várias maneiras usando streams, streams paralelos e o método removeIf :

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

O stream paralelo fará uso dos processadores disponíveis e acelerará o processo para listas de tamanho razoável. É sempre recomendável fazer benchmark antes de usar streams.

Semelhante a @Lithium answer mas não lança um erro “Lista não pode conter o tipo null”:

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