Como comparar objetos em Java?

Eu tenho uma lista de livros os quais já comprei:
public class Livro {
private String nome; 
private String autor;
private double preco;
public Livro(String nome, String autor, double preco) {
     this.nome = nome; 
     this.autor = autor; 
     this.preco = preco;
}
//métodos
}
List<Livro> meusLivros = todosOsLivros();
System.out.println(meusLivros);
Resultado:
 [TDD - Maurício Aniche, Java 8 - Paulo Silveira, C# - Everton Coimbra, REST - Alexandre Saudate, Android - João Bosco]
Agora testarei minha lista e verificarei se ela sabe conferir se um livro que já comprei está na lista:
Livro novo = new Livro("TDD", "Maurício Aniche", 25.00);
if (jaExiste(novo)) { 
    System.out.println("contém"); } else { 
        System.out.println("não contém"); 
        }
}
private static boolean jaExiste(Livro novo) { 
    if (todosOsLivros().contains(novo)) { 
        return true; 
        } 
        return false;
        }
 }
Resultado:
 não contém
Opa! Eu já comprei esse livro de TDD! Essa lista está doida? Ela não conseguiu verificar a existência desse livro, pois cada objeto possui um código chamado hashcode e é por meio desse código que qualquer objeto é identificado, por padrão. Vamos, por exemplo, imprimir dois objetos aparentemente "iguais" sem um toString() personalizado, ou seja, o padrão:
Livro livro1 = new Livro("TDD", "Maurício Aniche", 25.00);
Livro livro2 = new Livro("TDD", "Maurício Aniche", 25.00);
System.out.println(livro1); System.out.println(livro2);
Resultado:
 model.Livro@2a139a55 model.Livro@15db9742
Veja que, mesmo tendo as mesmas informações, as impressões foram diferentes! Por isso a lista informou que o livro de TDD não existia. Para personalizar a comparação de um objeto precisamos sobrescrever o método equals() herdado da classe [Object](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html):
public class Livro {
//métodos e atributos
@Override public boolean equals(Object obj) { //implementação }
}
Agora iremos implementar o método equals() informando que os livros são iguais desde que os nomes sejam iguais:
@Override public boolean equals(Object livro) { 
    if (this.nome == ((Livro) livro).getNome()){
         return true; } return false; }
Testando a nossa lista novamente:
Livro novo = new Livro("TDD", "Maurício Aniche", 25.00); 
if (jaExiste(novo)) { 
    System.out.println("contém"); } else { 
        System.out.println("não contém"); }
Resultado:
 contém
Maravilha! A nossa lista está conseguindo verificar se um determinado livro existe! Mas e se o autor for diferente? Ela vai informar que existe... Da mesma forma que informamos que queríamos a comparação do livro por meio do nome, podemos informar que queremos que o livro seja comparado pelo nome e autor, ao mesmo tempo:
@Override public boolean equals(Object livro) { 
if (this.nome == ((Livro) livro).getNome() && this.autor == ((Livro) livro).getAutor()){ return true; } return false; }
Vamos testar nossa lista novamente:
Livro novo = new Livro("TDD", "João da Silva", 25.00);
if (jaExiste(novo)) { 
    System.out.println("contém"); } else { 
        System.out.println("não contém"); } }
Resultado
 não contém
Agora todos os objetos do tipo Livro são corretamente comparados e, assim, eu posso sempre pedir para a minha lista de livros verificar se eu já tenho um determinado livro antes de comprá-lo! Todas as vezes que precisarmos fazer comparação entre objetos, será necessário sobrescrever o método equals() herdado da classe Object e implementar qual é o tipo de comparação que você precisa, seja por 1 atributo específico, ou por 2, ou por todos.
E aí, gostou da forma que comparamos objetos em Java? Que tal aprofundar mais nos detalhes dessa linguagem? Pensando nisso o instrutor Guilherme Silveira, criou a Formação Java na Alura.








