compareTo

18 respostas
evertonsilvagomesjav

Boa noite a todos!!

Galera eu to fazendo uns testes aqui e classificando aqui um ArrayList de produtos por nomes, ja consegui classificar, deu tudo certo implementei Comparable e sobrescrevi o compareTo.

A duvida vem pelo seguinte, no metodo abaixo é passado para á variavel local “prod” um objeto produto mas qual? O metodo Collections.sort() passa a lista de produtos para ele? Se eu tiver por exemplo cinco objetos produtos na lista e passado os cinco?

Seria isso que acontece nos bastidores ou eu to errado?

public int compareTo(Produto prod) { // TODO Auto-generated method stub return this.nome.compareTo(prod.getNome()); }

18 Respostas

hiram

Olá Everton,

Bem, o que acontece dentro do Collections.sort() pode ser qualquer coisa. Pode ser QuickSort, MergeSort.

O método Collections.sort() recebe uma List (no caso ArrayList) e lá dentro ele executa algum algoritmo de ordenação que usa o compareTo().

Segundo a documentação da API “The sorting algorithm is a modified mergesort…” (http://java.sun.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List)).

A documentação do Collections fala, inclusive, que você pode sobreescrever o método sort() utilizando outro algoritmo (contanto que este seja Estável - isto é, não trocar valores iguais de posição entre si durante a ordenação (vide Projeto e Análise de Algoritmos do autor Ziviani (UFMG))

Está claro?

[]'s
Hiram

evertonsilvagomesjav

+/- rs…o compareTo usa a tabela de hashing certo?

renamed

O método sort ordena qualquer tipo de lista que vc tenha… entretanto, ele não tem como saber como comparar uma classe que vc tenha feito… por exemplo… se vc tem a seguinte classe:

public class Pessoa {
	private String name;
	private int idade;
}

Como ele irá comparar? Pelo nome, pela idade?

Para resolver esse problema, o sort recebe, em uma de suas implementações, uma interface do tipo Comparator…
Vc pode não especificar o Comparator, mas olhe o que acontecerá:

public class Pessoa {
	private String name;
	private int idade;
	
	
	public Pessoa(String name, int idade) {
		super();
		this.name = name;
		this.idade = idade;
	}


	public static void main(String[] args) {
		List<Pessoa> lista = new ArrayList<Pessoa>();
		
		
		lista.add(new Pessoa("y", 63));
		lista.add(new Pessoa("r", 33));		
		lista.add(new Pessoa("a", 23));
		lista.add(new Pessoa("j", 53));
		lista.add(new Pessoa("z", 13));
		lista.add(new Pessoa("e", 43));
		lista.add(new Pessoa("s", 73));
		
		/*
		 * ERRO:
		 * Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable 
		 * for the arguments (List<Pessoa>). The inferred type Pessoa is not a valid substitute for 
		 * the bounded parameter <T extends Comparable<? super T>>
		 */
		Collections.sort(lista);
	}
}

Para solucionar, mande um new Comparator como parâmetro para o método sort!

public class Pessoa  {
	private String name;
	private int idade;
	
	
	public Pessoa(String name, int idade) {
		super();
		this.name = name;
		this.idade = idade;
	}


	public static void main(String[] args) {
		List<Pessoa> lista = new ArrayList<Pessoa>();
		
		
		lista.add(new Pessoa("y", 63));
		lista.add(new Pessoa("r", 33));		
		lista.add(new Pessoa("a", 23));
		lista.add(new Pessoa("j", 53));
		lista.add(new Pessoa("z", 13));
		lista.add(new Pessoa("e", 43));
		lista.add(new Pessoa("s", 73));
		
		Collections.sort(lista, new Comparator<Pessoa>(){

			@Override
			public int compare(Pessoa p1, Pessoa p2) {
				return p1.name.compareTo(p2.name);
			}
			
		});
		
		for(Pessoa p : lista){
			System.out.println(p.name);
		}
	}
}

Ele não passa todos, ele compara os 2 que está olhando pra saber qm e maior e poder posicioná-lo corretamente na lista…

ok?

ViniGodoy

Veja também: http://www.guj.com.br/posts/list/45985.java

sergiotaborda

Não. Hashing não tem nada a haver com ordenar. Tem a haver com procurar.

O algoritmo de ordenação, qualquer um, em algum ponto precisa comparar os objetos para estabelecer a relação de ordem. Os objetos são comparados dois a dois. É por isso que vc recebe um objeto em compareTo porque vc precisa comparar este objeto (this) com o objeto passado.

Se vc der uma olhada na interface Comparator que é prima de Comparable vc verá que são passados dois objetos.

Mais detalhes sobre comparação

evertonsilvagomesjav

eu to lendo tb o topico ai que Mantu falou sobre o compareTo mas ainda to meio confuso, pra entender qual objeto e passado aqui (Produto prod)…

e quanto ao compare(Produto prod1, Produto prod2)…

vou ler mais pra ver se consigo entender

sergiotaborda

evertonsilvagomesjava:
eu to lendo tb o topico ai que Mantu falou sobre o compareTo mas ainda to meio confuso, pra entender qual objeto e passado aqui (Produto prod)…

O objeto que é passado é um dos objetos da lista. Vc não precisa saber qual.

evertonsilvagomesjav

E exatamente isso que é minha duvida sergio, o objeto passado é um da lista ok…

Mas se eu tenho cinco objetos na lista por exemplo ai vem o metodo:

1. public int compareTo(Produto prod) { 2. // TODO Auto-generated method stub 3. return this.nome.compareTo(prod.getNome()); 4. }

Digamos que “prod” recebe o primeiro obj da lista, ele vai comparar a variavel de instancia
nome com o objeto.nome…

Essa comparaçao que eu achava que era feita com base em hashing pq ele retorna,

negativo se o thisObject < anotherObject
zero se thisObject == anotherObject
positivo se thisObject > anotherObject

como que um objeto vai ser menor igual ou maior que o outro? Teria que ser com base em numeros(hashing) nao?

renamed

Cara

O método sort precisa do compareTo para estabelecer uma hierarquia entre os 2 objetos, uma vez que esse método é genérico.

Por exemplo… estou ordenando uma lista genérica e me deparo com dois elementos: 2 e 3.

O método não sabe quem deve vir primeiro… não sabe nem se ambos são iguais. Ele chama o compareTo pra decidir por ele.

public int compareTo(int n1, int n2) {    
        if (n1 < n2) return -1; //n1 vem primeiro na ordenação
        if (n1 == n2) return 0; //ambos sao equivalentes na ordenação
        return 1;         //n1 vem depois de n2 na ordenação
     }

ok?

evertonsilvagomesjav

Humm ok agora outra coisa

public int compareTo(Produto prod) { // TODO Auto-generated method stub return this.nome.compareTo(prod.nome) // prod.nome da pra saber qual e o nome especifico passado, agora this.nome ele se refere diretamente a variavel de instancia nome mas com base em qual objeto? }

renamed

Se é this eu estou me referindo a uma coisa referente a mim!

Provavelmente esse compareTo está dentro de uma classe Produto.

Ele recebe por parametro um objeto Produto para comparar e ver se é igual a ele mesmo (ou seja, comparar se o nome dele (this) é igual ao nome do produto que ele recebeu por parênteses)…

Entendeu?

evertonsilvagomesjav

mas dessa forma this.nome vai ser sempre igual a prod.nome certo?

renamed

não.

evertonsilvagomesjav

=/

Se eu instancio por exemplo:

Produto p1 = new Produto();

p1.setNome(“Everton”);

this.nome e p1.nome…

num vai ser mesma coisa n? pra p1 a variavel nome ta setada como Everton…

renamed
public class Pessoa implements Comparable<Pessoa> {
	private String nome;
	

	public String getNome() {
		return nome;
	}


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


	@Override
	public int compareTo(Pessoa p) {
		return this.nome.compareTo(p.nome);
		
		//this.nome refere-se ao objeto a partir do qual o método foi chamado!
		//p.nome refere-se ao objeto passado por parâmetro
		//Logo, são dois objetos diferentes!
	}
	
	public static void main(String[] args) {
		Pessoa p1 = new Pessoa();
		Pessoa p2 = new Pessoa();
		Pessoa p3 = new Pessoa();
		Pessoa p4 = new Pessoa();
		
		p1.setNome("Fulano");
		p2.setNome("Beutrano");
		p3.setNome("Cicrano");
		p4.setNome("Fulano");
		
		System.out.println(p1.compareTo(p2)); //positivo ==> Fulano vem depois que Beutrano
		System.out.println(p3.compareTo(p4)); //negativo ==> Cicrano vem antes de Fulano
		System.out.println(p1.compareTo(p4)); //neutro ==> Fulano = Fulano
		
	}

}

agora foi?

sergiotaborda

evertonsilvagomesjava:
=/

Se eu instancio por exemplo:

Produto p1 = new Produto();

p1.setNome(“Everton”);

this.nome e p1.nome…

num vai ser mesma coisa n? pra p1 a variavel nome ta setada como Everton…

Antes de entender compareTo endenda OO primeiro e algoritmos de ordenação depois.

o algoritmo de comparar não vai comparar o objeto com ele mesmo. Isso seria absurdo e inutil.
Ele vai comparar dois objetos diferentes

por exemplo se vc tem os produtos A, B e C na lista assim :

CAB

o algoritmo fará o seguinte

pega o primeiro, C
pega o o segundo , A

A é menor que C ?
Se sim, troca-os de posição

A lista fica agora ACB

agora pega o segundo e o terceiro

C é menor que B ?
não.
C é maior que B?
sim. troca-os de lugar

o resultado é

ABC

O algoritmo verdadeiro é mais complexo, mas é para vc ter uma ideia que sempre a comparação é feita entre dois objetos diferentes

evertonsilvagomesjav

quanto ao this ficou claro agora que refere-se ao objeto que foi chamado ta meio confuso pq nao estou usando objeto chamando compareTo to usando assim o Collections.sort direto, por isso a duvida ao this...

package guj.exercicio;

public class Produto implements Comparable<Produto> {
	
	private String nome;
	private String cod;
	private Double preco;
	
	public void setNome(String nome){
		
		this.nome = nome;
		
	}
	
	public String getNome(){
		
		return this.nome;
		
	}
	
	public void setCod(String cod){
		
		this.cod = cod;
		
	}
	
	
	public String getCod(){
		
		return this.cod;
		
	}
	
	public void setPreco(double preco){
		
		this.preco = preco;
		
	}
	
	public double getPreco(){
		
		return this.preco;
		
	}

	@Override
	public int compareTo(Produto prod) {
		// TODO Auto-generated method stub
		return this.nome.compareTo(prod.getNome());
	}
	
}
package guj.exercicio;

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

public class GerenciadorProduto {

private ArrayList <Produto> listaProdutos = new ArrayList <Produto>();  
	  public void listaProduto(){
		  
		  Collections.sort(this.listaProdutos);
		  
		  for(Produto prod : this.listaProdutos){
			  
			  System.out.println(prod.getCod() +"\n" +prod.getNome() +"\n"
					  			+prod.getPreco());
			  
		  }
		  
	  } // fim do Método de listarProduto.
	
}

Da maneira que o renamed me mostrou o compareTo sendo chamado por um objeto ficou facil entender a comparaçao o problema e pq to usando ele da forma que mostrei a cima por isso me veio a dificuldade de entender o this.nome

evertonsilvagomesjav

Galera vlw a todos ai que me ajudaram, pelo que entendi entao dentro do Collections.sort que é feito a comparaçao com o compareTo usando dois objetos da lista por exemplo para ir fazendo a comparaçao e a ordenaçao…vlw galera!!!

Criado 22 de dezembro de 2009
Ultima resposta 24 de dez. de 2009
Respostas 18
Participantes 5