Capítulo 3 Os métodos equals() e hashCode() Equivalência de tipos primitivos Equivalência de String Equivalência de outros objetos O método equals() O método hashCode() A interface Comparable e o método compareTo() 2 Equivalência de tipos primitivos Para verificar a equivalência de valores primitivos utilizamos o operador == int x = 8; int y = 4 + 4; if (x == y) { System.out.println("Valores iguais."); } else { System.out.println("Valores diferentes."); } 3 Equivalência de Strings Para verificar a equivalência de valores String utilizamos o método equals() String temp = "nova"; String valor1 = "casanova"; String valor2 = "casa" + temp; if (valor1.equals(valor2)) { System.out.println("Strings iguais"); } else { System.out.println("Strings diferentes"); } 4 Equivalência de outros objetos Para verificar a equivalência de outros tipos de objetos também utilizamos o método equals() Funcionario f1 = new Funcionario(1021, "João", "Vendedor", 1815.5); Funcionario f2 = new Funcionario(.......); if (f1.equals(f2)) { System.out.println("Funcionarios iguais"); } else { System.out.println("Funcionarios diferentes"); } 5 O método equals() Um dos métodos derivados da superclasse Object Deve ser reimplementado (sobrescrito) pelo programador conforme necessidade da aplicação • clone() • equals(Object) • finalize() • getClass() • hashCode() • notify() • notifyAll() • toString() • wait() • wait(long) • wait(long, int) 6 Implementando o método equals() public class Funcionario { private int matricula; private String nome; private String cargo; private double salario; // ... métodos gets e sets public boolean equals(Object object) { if (!(object instanceof Funcionario)) return false; Funcionario outro = (Funcionario) object; return (this.matricula == outro.matricula); } } 7 Leis de igualdade Ao implementar o método equals(), certifique-se de atender as 4 leis de igualdade. Para isto seu método equals() deve ser: Simétrico Reflexivo Transitivo Consistente 8 Lei da simetria O método equals() precisar ser simétrico. Isto significa que a regra abaixo sempre deve ser verdadeira para qualquer instância de sua classe: objetoA.equals(objetoA) sempre deve ser verdade 9 Lei da reflexividade O método equals() precisar ser reflexivo. Isto significa que as expressões abaixo precisam ser equivalentes: objetoA.equals(objetoB) objetoB.equals(objetoA) 10 Lei da transitividade O método equals() precisar ser transitivo. objetoA.equals(objetoB) e objetoB.equals(objetoC) objetoA.equals(objetoC) 11 Lei da consistência O método equals() precisar ser consistente. Isto significa que chamadas sucessivas do método equals() não devem alterar o seu resultado. objetoA.equals(objetoB) objetoA.equals(objetoB) objetoA.equals(objetoB) ... objetoA.equals(objetoB) Devem retornar sempre o mesmo resultado 12 O método hashCode() Outro método derivado da superclasse Object Também deve ser reimplementado (sobrescrito) pelo programador conforme necessidade da aplicação • clone() • equals(Object) • finalize() • getClass() • hashCode() • notify() • notifyAll() • toString() • wait() • wait(long) • wait(long, int) 13 O método hashCode() Juntamente com o método equals(), o método hashCode() é utilizado para diferenciar um objeto de outro em estruturas de dados que não permitem repetição. equals() Diferencia um objeto de outro impedindo duplicidade em estruturas sem repetição. hashCode() Retorna um número inteiro utilizado como identificador único do objeto instanciado. 14 O método hashCode() Devemos nos preocupar em implementar o método hashCode() ao criar classes cujas instâncias serão utilizadas em estruturas de dados como listas, mapas, conjuntos, etc. Ao implementar o método hashCode() em uma classe, geralmente pegamos “carona” com o hashCode de cada um de seus membros para que possamos gerar um ID que dependa de cada um de seus atributos. 15 Implementando o método hashCode() public class Funcionario { private int matricula; private String nome; private String cargo; // ... métodos gets e sets public int hashCode() { int hash = 1; hash = 31 * hash + matricula; hash = 31 * hash + (nome == null ? 0 : nome.hashCode()); hash = 31 * hash + (cargo == null ? 0 : cargo.hashCode()); return hash; } } 16 A interface Comparable Assinala um critéria de comparação entre objetos, permitindo definir se um objeto é maior ou menor que um outro Deve ser implementado em classes cujas instâncias serão utilizadas em estruturas de dados ordenáveis. 17 Comparando tipos primitivos Para comparar valores primitivos utilizamos os operadores relacionais > (maior), < (menor) e outros int x = 8; int y = 4 + 6; if (x > y) { System.out.println(“O primeiro valor é maior."); } else if (x < y) { System.out.println(“O segundo valor é maior."); } else { System.out.println("Valores iguais."); } 18 Comparando Strings Para a comparação de valores String utilizamos o método compareTo() String valor1 = “Manuel"; String valor2 = “Joaquim”; if (valor1.compareTo(valor2) > 0) { System.out.println(“O primeiro String é maior"); } else if (valor1.compareTo(valor2) < 0) { System.out.println(“O segundo String é maior"); } else { System.out.println("Strings iguais"); } 19 Comparando outros objetos Para realizar a comparação de outros tipos de objetos também utilizamos o método compareTo() Funcionario f1 = new Funcionario(1021, "João", "Vendedor", 1815.5); Funcionario f2 = new Funcionario(.......); if (f1.compareTo(f2) > 0) { System.out.println(“O primeiro funcionario é maior"); } else if (f1.compareTo(f2) < 0) { System.out.println(“O segundo funcionario é maior"); } else { System.out.println("Funcionarios iguais"); } 20 Implementando a interface Comparable O método compareTo() só funciona em classes que implementam a interface java.lang.Comparable 21 Implementando a interface Comparable public class Funcionario implements Comparable<Funcionario> { private int matricula; private String nome; private String cargo; // ... métodos gets e sets public int compareTo(Funcionario outro) { if (this.nome.compareTo(outro.nome) > 0) { return 1; } else (this.nome.compareTo(outro.nome) < 0) { return -1; } else { return 0; } } } 22 Exercício Crie uma classe denominada Produto contendo os seguintes atributos: codigo: inteiro descricao: String preco: double Implemente os métodos get e set para cada um destes atributos Implemente o método equals() realizando a comparação pela descrição do produto. Em outras palavras, dois produtos serão iguais quando possuírem a mesma descrição. 23 Exercício (continuação) A classe Produto deverá implementar a interface Comparable<Produto> bem como seu método compareTo() realizando a comparação também pela descrição em ordem crescente. Em outras palavras, o método compareTo() deverá retornar: Um número positivo quando a descrição do item em questão for alfabeticamente maior que a descrição do outro produto Um número negativo quando contrário Zero quando tiverem a mesma descrição 24 Exercício (fim) Crie um classe executável chamada ExercicioComparable e no método main() crie 3 instâncias da classe produto conforme abaixo: Produto p1 = new Produto(805, “Leite Integral”, 1.70); Produto p2 = new Produto(930, “Café em pó”, 4.80); Produto p3 = new Produto(110, “Manteiga”, 2.80); Em seguida, exiba cada um dos produtos conforme a ordem definida pelo método compareTo() de cada objeto. 25