Check if Arraylist has identical items

Asked

Viewed 6,191 times

1

I have the class Pessoa:

String Nome, Cidade;

public Pessoa(String Nome, String Cidade){
    this.Nome = Nome;
    this.Cidade = Cidade;
}


public String getNome() {
    return Nome;
}

public String getCidade() {
    return Cidade;
}

I have the class that adds the Pessoas in a ArrayList:

ArrayList<Pessoas> pessoas = new ArrayList<>();

public void cadastrarPessoas(){
    Pessoa pessoa = new Pessoa(Nome, Cidade);
    pessoas.add(pessoa);
}

How can I return true if case in the list of persons contains the equal added element (example below): Person = new Person

Leandro|SP
Leandro|SP

As I wished:

Leandro|SP
Leandro|RC

I tried this way but nothing happens:

Pessoa pessoa2 = new Pessoa(Nome, Cidade);

    for (Pessoa pessoa : pessoas){
                if (pessoa.equals(pessoa2)){
                    iguais
                }else{
                    pessoas.add(pessoa2);
                    diferentes
                }
            }
  • 1

    Take a look, see if it helps you: Link

  • I forgot to mention that I wanted to do an if you have repeated, as I could do in the topic answer?

  • You need to make a Comparator or implement the equals method, here on the site already has it answered.

  • Edit your question, add the details, once you answer, have better idea than you need.

  • The equals method did not work, as I can do the comparator?

  • I’ve tried people.contains, equals and nothing

  • I suggest [Edit] the question, adding the code you already tried (the equals method, etc.), and what was the result and/or error message. Simply saying "I’ve tried and nothing" is too vague and does not help us to help you, because we have no way of knowing exactly where you are going wrong

  • I’ve already edited and put the code but it just doesn’t work, keeps adding people equal

  • You have to overwrite the method equals in class Pessoas, see an example here. Another thing (unrelated), is that the class Pessoas represents only one person, so I would change the name to Pessoa (singular). It may seem a silly detail, but for me it makes the code a little less confusing (it doesn’t confuse the variable pessoa with the list pessoas, etc.).

  • I think you got it wrong, I wanted to return true if the list People contains the: Person = new Person I will edit and explain better excuse.

  • And how do you think the method contains of a ArrayList makes to know if an element belongs to the list? Using the method equals. How is a ArrayList of Pessoas, the class Pessoas must have a method equals which says what the rule is for determining that two people are equal. Without this, the contains there’s no way of knowing if two people are the same, and so there’s no way of knowing if the person belongs to the list.

  • In the example I used equals, because I need to compare the whole list to see if it is equal to the new element I created, but nothing is happening. I don’t want to create two elements and compare the two

Show 7 more comments

1 answer

6


When you create the class Pessoa:

public class Pessoa {
    private String nome;
    private String cidade;

    public Pessoa(String nome, String cidade) {
        this.nome = nome;
        this.cidade = cidade;
    }

    // ... getters e setters
}

How do I know if 2 instances of this class are equal? The first idea is to use the operator ==, since it works for numbers, so why wouldn’t it work with objects?

// primeira tentativa de comparar 2 pessoas
Pessoa p1 = new Pessoa("Fulano", "SP");
Pessoa p2 = new Pessoa("Fulano", "SP");
System.out.println(p1 == p2); // false

Only this code prints false. That’s because the operator == checks whether p1 and p2 are the same object. As each one was created with new, they are 2 different objects (although with the same values).

Ah, but wait, there’s the method equals. Let’s try to use it?

// segunda tentativa de comparar 2 pessoas
Pessoa p1 = new Pessoa("Fulano", "SP");
Pessoa p2 = new Pessoa("Fulano", "SP");
System.out.println(p1.equals(p2)); // false

This code also prints false. This happens because the method equals was inherited from Object, and internally this method uses the operator ==. I traded six for half a dozen.


For me to consider 2 instances of Pessoa equal based on their values, I must overwrite the method equals. That is, the class Pessoa must have its own version of equals, with the rule that defines what makes 2 people equal.

In this case, 2 people are equal if their names and cities are the same, then the method would look like this:

public class Pessoa {
    ....

    @Override
    public boolean equals(Object obj) {
        Pessoa other = (Pessoa) obj;
        // verifica se o nome e cidade são iguais
        return this.nome.equals(other.nome) && this.cidade.equals(other.cidade);
    }
}

Of course this implementation can be improved by testing whether the fields are null, if obj is really an instance of Pessoa, etc, but let’s keep it simple for didactic purposes.

It is also important to overwrite the method hashCode. At this link there is a good response detailing the reasons and how to implement it properly. Here I leave the implementation suggested by Eclipse, but I suggest you read the link indicated to better understand this method:

public class Pessoa {
    ....
    // equals, getters, setters, construtor, etc

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((cidade == null) ? 0 : cidade.hashCode());
        result = prime * result + ((nome == null) ? 0 : nome.hashCode());
        return result;
    }
}

With that, now the class Pessoa can verify if another Pessoa is just like her:

// terceira tentativa de comparar 2 pessoas
Pessoa p1 = new Pessoa("Fulano", "SP");
Pessoa p2 = new Pessoa("Fulano", "SP");
System.out.println(p1.equals(p2)); // true

Now this code prints true.


With that, if you have a list of Pessoa, can easily check if any Pessoa already belongs to the list:

// cria a lista e insere pessoas nela
List<Pessoa> listaPessoas = new ArrayList<>();
listaPessoas.add(new Pessoa("Fulano", "SP"));
listaPessoas.add(new Pessoa("Fulano", "RC"));

// verifica se uma pessoa qualquer pertence à lista
Pessoa pessoa = new Pessoa("Fulano", "SP");
System.out.println(listaPessoas.contains(pessoa));

The method contains uses the method equals of Pessoa to find out if two people are the same, and so checks whether the pessoa already belongs to the list. This code above prints true ("Fulano/SP" belongs to the list).

Of course you could also do the for in the list and compare each person with the method equals, but why do it if contains does exactly the same thing?

Besides, you’re making one for in the list and adding an element to this list within the for, which will generate a java.util.ConcurrentModificationException. You better use contains even:

Pessoa pessoa = new Pessoa("Fulano", "SP");
// se a pessoa não pertence à lista, adiciona
if (! listaPessoas.contains(pessoa)) {
    listaPessoas.add(pessoa);
}

But if you want a collection of several people without having repeated, it is better to use a java.util.Set, for a set does not allow equal elements:

// usar Set ao invés de List
Set<Pessoa> setPessoas = new HashSet<>();
// inserir pessoas
setPessoas.add(new Pessoa("Fulano", "SP"));
setPessoas.add(new Pessoa("Fulano", "RC"));
// tentar inserir Fulano/SP de novo
setPessoas.add(new Pessoa("Fulano", "SP"));

// imprime o tamanho do set
System.out.println(setPessoas.size());

This code prints out 2, for the Set will only have 2 elements. The second attempt to insert "Fulano/SP" does not work, because it already belongs to the Set.

If I used List, would have to check if the element already belongs to the list before adding it (which also works, but use Set eliminates this step).


If even so you need a List, can create it from the Set:

// cria um List com os elementos do Set
List<Pessoa> listaPessoas = new ArrayList<>(setPessoas);

Another way to implement the hashCode is using a java.util.Objects (plural, not to be confused with java.lang.Object (in the singular)):

@Override
public int hashCode() {
    // calcula o hashCode usando nome e cidade
    return Objects.hash(cidade, nome);
}
  • Got it, I’m using contains in Set<> but it only returns false, List<> also returns only false when I used, and it’s very strange because the data is the same in List<> but I think in Set<> it does not add equal

  • @Exact Slinidy, in the List, the same elements can be inserted several times, in the Set no. But the Set will only know if 2 people are equal if you implement equals and hashCode

  • I don’t know what is happening more my Set<> is inserting repeated value, even with contains and can not insert, I will edit and show all values taken from for

  • @Slinidy Se the Set is accepting repeated, is pq the methods equals and hashCode are not correctly implemented

  • It worked thanks, could explain to me why you put prime = 31 result = 1 ?

  • @Slinidy I used the Eclipse automatic generator, which puts a standard implementation of it. In fact you can use qq number, as long as you obey some rules, as "if 2 people are equal (equals returns true), your hashCodes should also be equal, etc". I suggest that read the link I passed, that explains more details about the hashcode

  • @Slinidy You have a discussion about this: https://stackoverflow.com/questions/11795104/is-the-hashcode-function-generated-by-eclipse-anygood

  • @Now I have to leave, but any questions we can continue tomorrow. If your question is no longer related to equals and hashcode, I suggest you ask another question, so as not to mix up the subjects. Good evening!

  • My silly thing, it worked perfectly, thank you. Good evening!

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.