[Resolvido] Ordenar Lista de objetos pelo seu atributo tipo double com o método CompareTo

Bom dia, estou praticando alguns exercícios em java, e estou com a seguinte dificuldade em um deles. Preciso fazer uma ordenação por dois atributos.

Tenho os atributos Nome e Média no meu objeto Aluno, e preciso fazer a ordenação com base neles. As regras para ordenação é:

  • Ordenar pelo nome, caso tenha dois iguais, ordene pela maior média.

Implementei a interface Comparable na minha classe Aluno, e com isso o método compareTo.

package exercicio2;

public class Aluno implements Comparable<Aluno> {

	String nome;
	int nota1;
	int nota2;
	Double media;

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public Integer getNota1() {
		return nota1;
	}

	public void setNota1(Integer nota1) {
		this.nota1 = nota1;
	}

	public Integer getNota2() {
		return nota2;
	}

	public void setNota2(Integer nota2) {
		this.nota2 = nota2;
	}

	public Double getMedia() {
		return media;
	}

	public void setMedia(Double media) {
		this.media = media;
	}

	/*
	 * so pra constar, o compareTo tem 3 retornos possiveis, -1, 0 e 1 quando
	 * for -1 o numero é menor, 0 representa igualdade e 1 representa que é
	 * maior
	 */
	@Override
	public int compareTo(Aluno a) {

		//return media.compareTo(a.getMedia());
		
		int n = getNome().compareTo(a.getNome());

		if (n != 0) 
			return n;
		 else
			return media.compareTo(a.getMedia());
	}

}
package exercicio2;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

public class Main {

	public static void main(String[] args) {

		Aluno[] alunos = new Aluno[3];
		ArrayList<Aluno> lista = new ArrayList<Aluno>();

		String[] nomes = { "Luiza", "Dyego", "Luiza" };
		int[] nota1 = { 40, 90, 80 };
		int[] nota2 = { 30, 100, 40 };

		for (int i = 0; i < alunos.length; i++) {

			alunos[i] = new Aluno();
			alunos[i].nome = nomes[i];
			alunos[i].nota1 = nota1[i];
			alunos[i].nota2 = nota2[i];
			alunos[i].media = new Double((nota1[i] + nota2[i]) / 2);

			lista.add(alunos[i]);
		}

		// Ordenar os alunos
		// Regras: Ordenar pelos nomes, caso tenha dois alunos com nomes iguais,
		// vale a maior média;
		Collections.sort(lista);

		for (Iterator<Aluno> iterator = lista.iterator(); iterator.hasNext();) {
			Aluno aluno = (Aluno) iterator.next();
			System.out.println("Nome : " + aluno.getNome());
			System.out.println("Nota1: " + aluno.getNota1());
			System.out.println("Nota2: " + aluno.getNota2());
			System.out.println("Media: " + aluno.getMedia());
			System.out.println("Hash : " + aluno.hashCode());
			System.out.println("\n");
		}

	}

}

No código acima, estou verificando se os nomes não são iguais, se forem ele ordena pela média.

Ele ordena pelo nome corretamente, mas quando tenho o teste onde dois nomes são iguais, no caso “Luiza”, para ele ordenar pela média, não funciona. Simplesmente não ordena.

Gostaria da ajuda de vocês para resolver esse problema.

Agradeço desde já! Obrigado.

simples assim…

@Override  
public int compareTo(Aluno a) {  
  
if(this.getNome().equals(a.getNome())){
 return this.getMedia() - a.getMedia();
}else{
 return this.getNome.compareTo(a.getNome())
}

Simples e errado, já que getMedia retorna um double, não um int :slight_smile:

Não precisarias fazer o Collections.sort
se fizeres
Set lista = new TreeSet();
pq ele já vai adicionar ordenado.

desculpe, não reparei q era double, entao faz o compareTo

Obrigado pela resposta Kleberdamasco, só que testei o código e não ordenou. Apenas pelo nome mesmo. E como ele retornava um double, foi feito uma conversão para inteiro:

	@Override
	public int compareTo(Aluno a) {

		if(this.getNome().equals(a.getNome())){  
			return (int) (getMedia() - a.getMedia());  
			}else{  
			return this.getNome().compareTo(a.getNome());  
			} 		
	}

[quote=dyegocm]Obrigado pela resposta Kleberdamasco, só que testei o código e não ordenou. Apenas pelo nome mesmo. E como ele retornava um double, foi feito uma conversão para inteiro:

	@Override
	public int compareTo(Aluno a) {

		if(this.getNome().equals(a.getNome())){  
			return (int) (getMedia() - a.getMedia());  
			}else{  
			return this.getNome().compareTo(a.getNome());  
			} 		
	}

[/quote]

faz assim para ele ordenar pelo double tbem

if(this.getNome().equals(a.getNome())){  
			return new Double(getMedia()).compareTo(new Double(a.getMedia()));  
			}else{  
			return this.getNome().compareTo(a.getNome());  
			} 		
	}

kleberdamasco, a saída que tenho é essa:

Nome : Dyego
Nota1: 90
Nota2: 100
Media: 95.0
Hash : 7615385


Nome : Luiza
Nota1: 40
Nota2: 30
Media: 35.0
Hash : 15184449


Nome : Luiza
Nota1: 80
Nota2: 40
Media: 60.0
Hash : 23583040

A “Luiza” que tem a media 60, teria que ser a segunda na listagem. Será que estou fazendo algo errado?

	@Override
	public int compareTo(Aluno a) {

		if (this.getNome().equals(a.getNome())) {
			return new Double(getMedia()).compareTo(new Double(a.getMedia()));
		} else {
			return this.getNome().compareTo(a.getNome());
		}
	}

Obrigado pela atenção.

[quote=dyegocm]kleberdamasco, a saída que tenho é essa:

Nome : Dyego
Nota1: 90
Nota2: 100
Media: 95.0
Hash : 7615385


Nome : Luiza
Nota1: 40
Nota2: 30
Media: 35.0
Hash : 15184449


Nome : Luiza
Nota1: 80
Nota2: 40
Media: 60.0
Hash : 23583040

A “Luiza” que tem a media 60, teria que ser a segunda na listagem. Será que estou fazendo algo errado?

	@Override
	public int compareTo(Aluno a) {

		if (this.getNome().equals(a.getNome())) {
			return new Double(getMedia()).compareTo(new Double(a.getMedia()));
		} else {
			return this.getNome().compareTo(a.getNome());
		}
	}

Obrigado pela atenção.[/quote]

para desencargo de consciência põe o this na frente do getMedia()

if (this.getNome().equals(a.getNome())) {
			return new Double(this.getMedia()).compareTo(new Double(a.getMedia()));
		} else {
			return this.getNome().compareTo(a.getNome());
		}

a de média 60 era sim para estar na frente.

Coloquei o “this” na frente do “getMedia()” mas mesmo assim não ordenou. A “Luiza” com média 35.0 ainda ficou na frente.

Obrigado.

[quote=dyegocm]Coloquei o “this” na frente do “getMedia()” mas mesmo assim não ordenou. A “Luiza” com média 35.0 ainda ficou na frente.

Obrigado.[/quote]

Você ta fazendo algo de errado,

vc está usando qual interface, List ou Set?
está fazendo o Collections.sort ?

uma coisa, como vc quer do maior para o menor, vc tem q inverter a comparação do objeto que está entrando no compareTo para o this.
a.getNome().compareTo(this…) desta forma.

Amigo, você está sofrendo do mal de “definir o problema incorretamente”.

Você não disse que os alunos tinham de ser listados em ordem CRESCENTE quanto ao nome, e DECRESCENTE quanto à nota :frowning: :frowning: :frowning:

Se esse é o seu desejo, então mude a comparação para inverter a ordem da comparação no caso do campo nota.

Em vez de x.compare(y), use y.compare(x) (!)

if(vc fizer assim) {
Set<Aluno> a = new TreeSet<Aluno>();
NÃO precisa utilizar o Collections.sort(a);
} senao {
List<Aluno> a = new ArrayList<Aluno>();
Collections.sort(a);
}

e antes de tudo, defina a regra que vc quer! :smiley:

kleberdamasco, muito obrigado pela atenção e a paciência.

entanglement realmente foi definido incorretamente, mil desculpas.

Mas agora deu certo. Mudei a ordem da comparação conforme vocês falaram, e funcionou. Adicionei mais pessoas e ordenou corretamente.

Nome : Dyego
Nota1: 90
Nota2: 100
Media: 95.0
Hash : 7615385


Nome : Dyego
Nota1: 20
Nota2: 16
Media: 18.0
Hash : 15184449


Nome : Luiza
Nota1: 80
Nota2: 40
Media: 60.0
Hash : 23583040


Nome : Luiza
Nota1: 40
Nota2: 30
Media: 35.0
Hash : 15218962


Nome : Vagner
Nota1: 66
Nota2: 96
Media: 81.0
Hash : 33219526

Para fins de pesquisa sobre a solução do problema do tópico, como ficou o método:

	@Override
	public int compareTo(Aluno a) {
		if (this.getNome().equals(a.getNome())) {
			return new Double(a.getMedia()).compareTo(new Double(this
					.getMedia()));
		} else {
			return this.getNome().compareTo(a.getNome());
		}
	}

Muito obrigado a vocês dois, e desculpe por qualquer coisa. Abraços. :slight_smile: