Compare different ArrayList's in Java

2

Good evening I would like you to help me in the following:

I have 2 ArrayList's:

ArrayList<Persona> listaPersona;

that its content transforming it into Json is the following:

[{"nombre":"Luis", "edad":"22"},{"nombre":"Juan","edad":"24"},
  "nombre":"Jose","edad":"15"}]

Now, I have another ArrayList:

ArrayList<String> nombres=new ArrayList(); 
nombres.add("Luis");
nombres.add("Juan");

What can I do to remove from my "Personlist" the entire row that does not contain the name of my ArrayList "names"?

I would like my ArrayList<Persona> to be as follows:

[{"nombre":"Jose","edad":"15"}]

I tried to do it in the following way:

for (int i=0; i<listaPersona.size(); i++) {
    for (int j=0; j<nombres.size(); j++) {
        if(!listaPersona.get(i).getNombre().equals(nombres.get(j))) {

            listaPersona.remove(i);
            i--;
        }
    }
}

But it is not the correct way since in the first iteration, Luis is compared with Juan and since they are not equal the row is eliminated, and that is what I do not want, I would greatly appreciate your help! Thanks in advance

    
asked by Luis Yul 03.05.2018 в 03:39
source

3 answers

1

First of all, what you say you want:

  

How could I remove the entire row from my "Personlist"?   does not contain the name of my ArrayList "names"?

It is not the same as what you expect as a result:

  

I would like my ArrayList to be as follows:

     

[{"name": "Jose", "age": "15"}]

Regardless of what you really want, if you keep the people who are in the list of names or delete those that are in that list. It is resolved in the same way.

To achieve what you want you have to perform 2 sequential searches as you are doing:

for (int i = 0; i < listaPersona.size(); i++) {
    for (int j = 0; j < nombres.size(); j++) {
        //persona en indice i esta en listado de nombres?
    }
}

But that question is not answered in a single iteration of j , but in all that loop:

for (int i = 0; i < listaPersona.size(); i++) {
    //persona en indice i esta en listado de nombres?
    boolean estaEnNombres = false;
    for (int j = 0; j < nombres.size(); j++) {
        if (listaPersona.get(i).getNombre().equals(nombres.get(j))) {
            estaEnNombres = true;
            break;
        }
    }
    if (estaEnNombres) {
        listaPersona.remove(i);
        i--;
    }
}

Now, what you do you can rewrite using the List API, like the contains method:

for (int i = 0; i < listaPersona.size(); i++) {
    boolean estaEnNombres = nombres.contains(listaPersona.get(i).getNombre());

    if (estaEnNombres) {
        listaPersona.remove(i);
        i--;
    }
}

Or even shorter, using removeIf :

listaPersona.removeIf((p) -> nombres.contains(p.getNombre()));
    
answered by 03.05.2018 / 04:33
source
2

Considering the following Person class.

public class Persona {
    private String nombre;
    private String edad;

    public Persona(String nombre, String edad) {
        super();
        this.nombre = nombre;
        this.edad = edad;
    }
    public String getNombre() {
        return nombre;
    }
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    public String getEdad() {
        return edad;
    }
    public void setEdad(String edad) {
        this.edad = edad;
    }
    @Override
    public String toString() {
        return "Persona [nombre=" + nombre + ", edad=" + edad + "]";
    }
}

We create the Test class to test the request.

public class Test {

    public static void main(String[] args) {
        List<Persona> listaPersona = new ArrayList<>();
        listaPersona.add(new Persona("Luis","22"));
        listaPersona.add(new Persona("Juan","24"));
        listaPersona.add(new Persona("Jose","15"));

        List<String> nombres = new ArrayList<>(); 
        nombres.add("Luis");
        nombres.add("Juan");

        for(String nombre: nombres){
            listaPersona.removeIf(p -> p.getNombre().equals(nombre));
        }

        System.out.println(listaPersona);
    }
}

We get as a result.

[Persona [nombre=Jose, edad=15]]

Explanation

To go through our list names we use a for-each, within each iteration we verify if the name (local variable in the iteration) matches with a name of > Person in our Personlist list; if this is the case we use the removeIf method (introduced in Java 8). The removeIf method accepts a lambda (Predicate in our case), if the comparison of Strings is true ( p.getName (). Equals (name) ) the Person is removed from our Personlist list.

    
answered by 03.05.2018 в 04:55
1

The first problem you are having is because, as you yourself say, "by not being the same the row is deleted" and what you want is the opposite. Well the denial (!) Is in the if .

if(!listaPersona.get(i).getNombre().equals(nombres.get(j)))

The other problem is that you have to spare the i-- that you use when you delete. This causes that when you eliminate an element from the list, in the next iteration of the for nested, it analyzes, once again, the previous element that you delete. For example, if we have this collection [1, 5, 3], and we eliminate the element from position 1 (the 5), the next one would take its place and therefore be located in the same position (the 1): [1, 3]. So in the next iteration, we have to re-analyze the same position from where we eliminate. Worse yet, in the case that the one from position 0 is eliminated, in the next iteration we would have a IndexOutOfBoundsException since the i will be -1 .

The correct solution would be this

for(int i=0; i<listaPersona.size(); i++) {
    for(int j=0; j<nombres.size(); j++) {
        if(listaPersona.get(i).getNombre().equals(nombres.get(j))) {
            listaPersona.remove(i);
        }
    }
}
  

NOTE: You lacked in the code that you shared the parenthesis that closes the first for . But I imagine that it was a mistake to transcribe the code, because otherwise you would have compilation errors.

However, unless you are forced to go through the collections manually, I share a better solution using an iterator ( Iterator ) and the method contains() of the class String .

Iterator<Persona> iter = listaPersona.iterator();
while (iter.hasNext()) {
    if (nombres.contains(iter.next().getNombre())) {
        iter.remove();
    }
} 
    
answered by 03.05.2018 в 04:23