Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Como pesquisar um aluno pelo nome e pela matricula

Pessoal, havia criado um tópico com esse mesmo assunto, achei que tinha solucionado o problema, porém ele persiste.

eu modifiquei a Classe equals de Aluno:

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Aluno other = (Aluno) obj;
        if (matricula == other.matricula || nome == other.nome) 
                return true;
        if (nome == null) {
            if (other.nome != null)
                return false;
        } else if (!nome.equals(other.nome))
            return false;
        return true;
    }

Quando eu faço uma busca com o contains que está no método estaMatriculado() da Classe Curso, ele não acha o aluno matriculado, mas se eu uso método equals a partir de uma instância de aluno comparada com outro aluno ele faz correto. Na lógica que eu criei pro método equals ele pesquisa se um aluno é igual a outro caso o nome ou a matricula sejam iguais.

    public boolean estaMatriculado(Aluno aluno) {
        return alunos.contains(aluno);
    }

Alguém consegue me dizer o porque o contais não está encontrando o aluno ?

6 respostas

Em quais casos o aluno não é encontrado? Eu fiz o código abaixo pra testar seu equals() e o resultado foi correto.

package br.com.alura;

public class TestaAluno {

    public static void main(String[] args) {

        String nomeAluno = "nomeAluno";
        String nomeOutro = "nomeOutro";
        int matrAluno = 123;
        int matrOutro = 456;

        Aluno aluno = new Aluno(matrAluno, nomeAluno);
        Aluno mesmo = new Aluno(matrAluno, nomeAluno);
        Aluno outro = new Aluno(matrOutro, nomeOutro);
        Aluno msmNome = new Aluno(matrOutro, nomeAluno);
        Aluno msmMatr = new Aluno(matrAluno, nomeOutro);        
        Aluno msmNulo = new Aluno(matrAluno, null);
        Aluno outroNulo = new Aluno(matrOutro, null);

        Curso curso = new Curso("Curso Teste", "Instrutor Teste");

        curso.matricula(aluno);
        System.out.println("Mesmo objeto               : " + curso.estaMatriculado(aluno));
        System.out.println("Mesmo nome, mesma matricula: " + curso.estaMatriculado(mesmo));
        System.out.println("Outro nome, outra matricula: " + curso.estaMatriculado(outro));
        System.out.println("Mesmo nome, outra matricula: " + curso.estaMatriculado(msmNome));
        System.out.println("Outro nome, mesma matricula: " + curso.estaMatriculado(msmMatr));
        System.out.println("Nome null, mesma matricula : " + curso.estaMatriculado(msmNulo));
        System.out.println("Nome null, outra matricula : " + curso.estaMatriculado(outroNulo));
    }
}

Saída:

Mesmo objeto               : true
Mesmo nome, mesma matricula: true
Outro nome, outra matricula: false
Mesmo nome, outra matricula: true
Outro nome, mesma matricula: true
Nome null, mesma matricula : true
Nome null, outra matricula : false

Eu usei o seu exemplo e a saída foi :

Mesmo objeto               : true
Mesmo nome, mesma matricula: true
Outro nome, outra matricula: false
Mesmo nome, outra matricula: false
Outro nome, mesma matricula: false
Nome null, mesma matricula : false
Nome null, outra matricula : false

Fala Alan! Eu adicionei algumas saídas pra gente tentar entender o que seu código está fazendo. Roda este código abaixo e veja posta o resultado aqui, por favor.

@Override
    public boolean equals(Object obj) {
        if (this == obj) {
            System.out.print("MESMO OBJETO                    - ");
            return true;
        }
        if (obj == null) {
            System.out.print("OUTRO OBJETO É NULO             - ");
            return false;
        }
        if (getClass() != obj.getClass()) {
            System.out.print("CLASSES DIFERENTES              - ");
            return false;
        }
        Aluno other = (Aluno) obj;
        if (matricula == other.matricula || nome == other.nome) {
            System.out.print("NOME OU MATRICULA IGUAIS        - ");
            return true;
        }
        if (nome == null) {
            if (other.nome != null) {
                System.out.print("NOME ALUNO NULO E O OUTRO NÃO   - ");
                return false;
            }
        } else if (!nome.equals(other.nome)) {
            System.out.print("NOMES DIFERENTES (MATRICULA TB) - ");
            return false;
        }
        System.out.print("RETURN FINAL                    - ");
        return true;
    }

Alterei um pouco o TestaAluno. Da parte que cria o curso até o fim do método, coloque o código abaixo:

        Curso curso = new Curso("Curso Teste", "Instrutor Teste");

        curso.matricula(aluno);
        System.out.println(aluno.equals(curso));
        System.out.println("Mesmo objeto               : " + curso.estaMatriculado(aluno));
        System.out.println("Outro objeto é nulo        : " + curso.equals(null));
        System.out.println("Mesmo nome, mesma matricula: " + curso.estaMatriculado(mesmo));
        System.out.println("Outro nome, outra matricula: " + curso.estaMatriculado(outro));
        System.out.println("Mesmo nome, outra matricula: " + curso.estaMatriculado(msmNome));
        System.out.println("Outro nome, mesma matricula: " + curso.estaMatriculado(msmMatr));
        System.out.println("Nome null, mesma matricula : " + curso.estaMatriculado(msmNulo));
        System.out.println("Nome null, outra matricula : " + curso.estaMatriculado(outroNulo));

A saída foi:

CLASSES DIFERENTES              - false
MESMO OBJETO                    - Mesmo objeto               : true
Outro objeto é nulo        : false
NOME OU MATRICULA IGUAIS        - Mesmo nome, mesma matricula: true
NOMES DIFERENTES (MATRICULA TB) - Outro nome, outra matricula: false
NOME OU MATRICULA IGUAIS        - Mesmo nome, outra matricula: true
NOME OU MATRICULA IGUAIS        - Outro nome, mesma matricula: true
NOME OU MATRICULA IGUAIS        - Nome null, mesma matricula : true
NOME ALUNO NULO E O OUTRO NÃO   - Nome null, outra matricula : false

Seu código está bom, mas tem algumas coisas que poderiam ser melhoradas:

  • Vc não precisa testar se o segundo aluno é um objeto nulo, pq o equals já retorna false sem nem invocar o método sobrescrito. (Veja como o resultado do método acima não chegou a imprimir a parte do "O OUTRO OBJETO É NULO")
  • Depois que vc testar se matricula ou nome são iguais, pode dar um return false, pq não vai existir mais casos de igualdade.

Fiz exatamente o que vc colocou acima, porém o resultado foi :

CLASSES DIFERENTES              - false
Mesmo objeto               : true
Outro objeto é nulo        : false
NOME OU MATRICULA IGUAIS        - Mesmo nome, mesma matricula: true
Outro nome, outra matricula: false
Mesmo nome, outra matricula: false
Outro nome, mesma matricula: false
Nome null, mesma matricula : false
Nome null, outra matricula : false

Meu método estaMatriculado da Classe Curso:

public boolean estaMatriculado(Aluno aluno) {
        return alunos.contains(aluno);
    }

Método hashCode da Classe Aluno:

//    Método criado a partir do eclipse
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + matricula;
        result = prime * result + ((nome == null) ? 0 : nome.hashCode());
        return result;
    }

Método equals da Classe Aluno:

@Override
    public boolean equals(Object obj) {
        if (this == obj) {
            System.out.print("MESMO OBJETO                    - ");
            return true;
        }
        if (obj == null) {
            System.out.print("OUTRO OBJETO É NULO             - ");
            return false;
        }
        if (getClass() != obj.getClass()) {
            System.out.print("CLASSES DIFERENTES              - ");
            return false;
        }
        Aluno other = (Aluno) obj;
        if (matricula == other.matricula || nome == other.nome) {
            System.out.print("NOME OU MATRICULA IGUAIS        - ");
            return true;
        }
        if (nome == null) {
            if (other.nome != null) {
                System.out.print("NOME ALUNO NULO E O OUTRO NÃO   - ");
                return false;
            }
        } else if (!nome.equals(other.nome)) {
            System.out.print("NOMES DIFERENTES (MATRICULA TB) - ");
            return false;
        }
        System.out.print("RETURN FINAL                    - ");
        return true;
    }
solução!

Entendi e consegui simular seu problema aqui. Se você está sobrescrevendo seu método hashCode(), deve estar usando um HashSet.

O erro ocorre porque os objetos não estão sendo encontrados, devido à organização que você montou no seu método hashCode().

Como você utiliza no cálculo tanto a matrícula quanto o nome, ao efetuar o cálculo do hashCode, o valor obtido pro aluno é X (o objeto é armazenado no local X). Alterando-se a matrícula ou o nome, o resultado do hashCode será Y. Com isso seu novo objeto está sendo armazenado no local Y.

Ao tentar buscar, se você ver pelos seus resultados, quando foram usados objetos diferentes, o método equals() nem foi chamado.

Você deveria bolar uma lógica que todos os objetos com mesma matrícula resultem no mesmo HashCode, mas que também todos com mesmo nome resultem também no mesmo HashCode. Mas acho que isso não é possível.

Acho que para sua proposta de encontrar alunos que tenham matricula ou nome iguais, o hashSet não seja a melhor solução. Se você fizer um método hashCode que só leva em conta a matrícula, não será possível encontrar alunos de mesmo nome e se fizer um hashCode que só leve em conta os nomes, não será possível encontrar alunos com mesma matrícula.

Talvez o ideal para este problema seria utilizar uma lista (foi o que eu usei nos testes iniciais).

Espero ter ajudado.

Foi isso mesmo Alexandre, terei que rever minha lógica, talvez refazer com o hashTable.

Valeu pela ajuda