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);
}
Take a look, see if it helps you: Link
– rbz
I forgot to mention that I wanted to do an if you have repeated, as I could do in the topic answer?
– Slinidy
You need to make a Comparator or implement the equals method, here on the site already has it answered.
– user28595
Edit your question, add the details, once you answer, have better idea than you need.
– rbz
The equals method did not work, as I can do the comparator?
– Slinidy
I’ve tried people.contains, equals and nothing
– Slinidy
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
– hkotsubo
I’ve already edited and put the code but it just doesn’t work, keeps adding people equal
– Slinidy
You have to overwrite the method
equals
in classPessoas
, see an example here. Another thing (unrelated), is that the classPessoas
represents only one person, so I would change the name toPessoa
(singular). It may seem a silly detail, but for me it makes the code a little less confusing (it doesn’t confuse the variablepessoa
with the listpessoas
, etc.).– hkotsubo
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.
– Slinidy
And how do you think the method
contains
of aArrayList
makes to know if an element belongs to the list? Using the methodequals
. How is aArrayList
ofPessoas
, the classPessoas
must have a methodequals
which says what the rule is for determining that two people are equal. Without this, thecontains
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.– hkotsubo
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
– Slinidy