Remove elements from an array that are already in another array

1

Dear, I have an initial student array and an array of new students. How can I do to obtain an array of new students that are not in the initial student array? This using java lambdas.

UPDATE


List listaFinal = new ArrayList();

for (Alumno nuevo : listaNuevos) {
    if (!listaRegistrados.stream().anyMatch(e -> e.getNombre() == nuevo.getNombre())) {
        listaFinal.add(nuevo);
    }
}

It works but I would like to know if there is a simpler or more intimate way. Also, I would like to know if there would be any problem if I wanted to use parallelStream

    
asked by Jhon Anaya Valiente 14.11.2017 в 23:21
source

2 answers

1

I propose the following solution, which is inexpensive at the resource level.

  • We create a Set with the student names of listExiste .
  • We compare that set with the list of new students, taking out those that are not contained in that set.
  • I've done the test with my class Persona to not have to create a class Alumno . In your case, it will be a matter of adapting it.

    I hope it serves you.

        /*Datos de prueba*/
        ArrayList<Persona> listExiste = new ArrayList<>();
        listExiste.add(new Persona("Pedro",50));
        listExiste.add(new Persona("Santiago",30));
        listExiste.add(new Persona("Juan",20));
    
        ArrayList<Persona> listNueva = new ArrayList<>();
        listNueva.add(new Persona("Pedro",50));
        listNueva.add(new Persona("Juan",20));
        listNueva.add(new Persona("Andrés",55));
        listNueva.add(new Persona("Mateo",38));
    
        /*Obtenemos los nombres de la lista vieja*/
        Set<String> existeNombres = 
            listExiste.stream()
                       .map(Persona::getNombre)
                       .collect(Collectors.toSet());
    
        /*Comparamos con la nueva*/
        List<Persona> listResultado =
             listNueva.stream()
                    .filter(e -> !existeNombres.contains(e.getNombre()))
                    .collect(Collectors.toList());
    
        System.out.println(listResultado.toString());
    

    Output :

    debug:
    [Andrés: 55 años, Mateo: 38 años]
    BUILD SUCCESSFUL (total time: 1 second)
    
        
    answered by 15.11.2017 / 03:32
    source
    0

    With the new Streams syntax, it is very easy to write compact code without realizing the real cost.

    In your case, apart from the for loop, there is another loop behind the anyMatch . So it is a loop inside another loop. If the lists are large, you may come to feel that it is not very efficient.

    The way I would do it is to first convert listaRegistrados to HashMap with the name as a key.

    Then I can iterate the listaNuevos list and efficiently filter the students by checking the hashmap.

    Using the Streams API, it would look like this:

    Map<String, Alumno> registradosMap = listaRegistrados.stream()
            .collect(Collectors.toMap(Alumno::getNombre, Function.identity()));
    
    List<Alumno> listaFinal = listaNuevos.stream()
            .filter(a -> !registradosMap.containsKey(a.getNombre()))
            .collect(Collectors.toList());
    

    Note: I am assuming that both listaRegistrados and listaNuevos are of type List<Alumno> . Although you have not stated it in that way in the question, that would be the right thing to do.

        
    answered by 15.11.2017 в 01:01