Filtrando elementos de dentro de um Array (Lista)

Hello guys! Eu tenho que consertar um código em um exercício e não consigo, porque faz algum tempo que não mexo com Java. Eu quero remover determinados elementos dentro de um array mediante uma condicional. Ex: Se N % 2 for 0 então este número é par, daí o algoritmo trata do elemento, adiciona, remove, coloca em outro array, no caso, eu quero remover e não tô sabendo muito bem como fazer. Olhei aqui no fórum algumas perguntas relativas, mas nada que ajudasse na resolução deste exercício, grato!

import java.util.List;

public class Kata13December {
    public static List<Integer> filterOddNumber(List<Integer> listOfNumbers){
        for (int i = 0; i < listOfNumbers.size(); i++){
            if (listOfNumbers(i%2) == 0){
                listOfNumbers.remove(i);
            }
        }
        return listOfNumbers;
    }
}

Isso aqui não faz sentido. O que vc tem que fazer é pegar o elemento da posição i e ver se o valor dele é par. Ou seja:

if (listOfNumbers.get(i) % 2 == 0) {

Mas ainda tem outro problema, pois remover itens de uma lista no mesmo loop que itera nela da forma que você fez não vai funcionar sempre.

Vou modificar um pouco o código para você entender:

public static List<Integer> filterOddNumber(List<Integer> listOfNumbers) {
    for (int i = 0; i < listOfNumbers.size(); i++) {
        System.out.println("Verificando índice " + i + ", lista=" + listOfNumbers);
        if (listOfNumbers.get(i) % 2 == 0) {
            System.out.println("removendo índice " + i);
            listOfNumbers.remove(i);
        }
    }
    return listOfNumbers;
}

E vamos testar assim:

List<Integer> lista = new ArrayList<>();
lista.add(2);
lista.add(4);
lista.add(7);
System.out.println(filterOddNumber(lista));

O resultado é:

Verificando índice 0, lista=[2, 4, 7]
removendo índice 0
Verificando índice 1, lista=[4, 7]
[4, 7]

Ou seja, primeiro ele verifica o elemento no índice zero (que é o número 2), verifica que é par e remove.

Na segunda iteração (quando i é igual a 1), o 2 já foi removido, então a lista agora só tem 4 e 7, e o elemento na posição 1 é o 7. Ou seja, o 4 foi “pulado”, por isso a lista acabou tendo o 4 e o 7.

Para evitar este problema, a maneira recomendada de remover elementos de uma lista no mesmo loop que itera nela é usar um java.util.Iterator:

public static List<Integer> filterOddNumber(List<Integer> listOfNumbers) {
    Iterator<Integer> it = listOfNumbers.iterator();
    while (it.hasNext()) {
        int n = it.next();
        if (n % 2 == 0) {
            it.remove();
        }
    }
    return listOfNumbers;
}

Agora sim, usando a lista do teste acima, ele remove tanto o 2 quanto o 4, e a lista final tem só o 7.

Repare que nesse caso, como a própria lista é modificada dentro do método, eu nem precisaria retorná-la e daria para usar assim:

List<Integer> lista = new ArrayList<>();
lista.add(2);
lista.add(4);
lista.add(7);
filterOddNumber(lista); // lista é modificada dentro do método, não precisa pegar o retorno
System.out.println(lista); // [7]
1 curtida

Usando streams o código pode ficar bem mais limpo…

    List<Integer> lista = new ArrayList<>();
    lista.add(2);
    lista.add(4);
    lista.add(7);
    lista.removeIf(n -> n % 2 == 0); // apenas necessitas desta linha
    System.out.println(lista);
1 curtida