Ordenar um HashMap usando o Compare ou Compare to

11 respostas
E

Olá eu tenho uma classe chamada placar que possui o nome e a pontuação de um jogador, e eu tenho outra classe chamada Records que ira armazenar em ordem todos os placar dos jogos, nessa classe records eu tenho dois hashmap(um armazena os records sem esta ordenado e o outro ordenado) e uma LinkedList. Para ordenar estou usando um Collections.sort, mas o professor disse que naum quer assim, ele disse que quer que usemos o compare ou algo assim.

Alguem pode me dar uma luz, pois da maneira que o prefessor tah pedindo eu até axei algo explicando, mas naum consegui entender, estou anexando minha duas classes, que por sinal esta funcionando pefeitamente, mas naum como o professor quer.

e ja ia me esquecendo, eu tenho que ordenar primeiro pela pontuação, e se tiver duas pontuações iguais ae pelo nome.

package br.Uemg.JodoDados.Model;

import java.util.*;

public class Records {

    Map<Integer, Placar> mapRecord = new HashMap<Integer, Placar>();
    List<Integer> lista = new LinkedList<Integer>();
    Map<Integer, Placar> mapRecordOrdenado = new HashMap<Integer, Placar>();

    public void gravarRecord(Placar placar) {
        int cont = 0;
        for (int i = 0; i <= lista.size() - 1; i++) {
            if (lista.get(i).equals(placar.getResultado())) {
                cont = 1;
            }
        }
        if (cont == 0) {
            lista.add(new Integer(placar.getResultado()));
        }
        mapRecord.put(mapRecord.size() + 1, placar);

    }

    public void ordenar() {
        Integer x = 1;
        Collections.sort(lista);
        for (int j = lista.size(); j > 0; j--) {
            for (Integer i = 1; i <= mapRecord.size(); i++) {
                if (mapRecord.get(i).getResultado().equals(lista.get(j - 1))) {
                    mapRecordOrdenado.put(x, mapRecord.get(i));
                    x++;
                }
            }
        }
    }

    public Map mostrarRecord() {
        ordenar();
        return mapRecordOrdenado;
    }
}
package br.Uemg.JodoDados.Model;

import java.util.Observable;

public class Placar extends Observable {

    private Jogador jogador;
    private Integer resultado;

    public Jogador getJogador() {
        return jogador;
    }

    public void setJogador(Jogador jogador) {
        this.jogador = jogador;
    }

    public Integer getResultado() {
        return resultado;
    }

    public void setResultado(Integer resultado) {
        this.resultado = resultado;
    }
}

11 Respostas

Lavieri

se vc quer Maps ordenados então vc precisa usar TreeMap, e não HashMap... pelo que vc falou, vc quer ordenar o mapa pelo placar, e depois pelo nome, caso o placar seja igual...

1° lugar o seguinte... pra que o MAP ? não entendi a função dele.. qual a função do Integer, Placa ?? ... enfim não vou entrar no merito disso... c vc ker ordenar... então seria assim

vc precisa comparar o value e não a key, então vai ter q fazer um comparator 1 pouco complicado... veja abaixo como seria...

private static class CompararPlacars implements Comparator<Integer> {
        
        private Map<Integer,Placar> placar;
        
        public void setPlacar(Map<Integer,Placar> placar) {
            this.placar = placar;
        }
        
        public int compare(Integer o1, Integer o2) {
            Placar p1 = placar.get(o1);
            Placar p2 = placar.get(o2);
            int result = p1.getResultado().compareTo(p2.getResultado()); //compara os resultados
            if (result == 0) //se o resultado for igual
                result = p1.getJogador().getNome().compareTo(p2.getJogador().getNome()); //compara os nomes
            return result;
        }
    }

ai vai ter q falar para o comparator quem é o map, se não fica impossivel descobrir os placares, já que a ordem de um Map é feito pela KEY e não pelo value...

CompararPlacars compara = new CompararPlacars();
        TreeMap<Integer,Placar> records = new TreeMap<Integer, Placar>(compara);
        compara.setPlacar(records);

Criado assim o meu TreeMap, ele vai ser ordenado automaticamente a cada entrada... vai sempre se manter na ordem especificada pelo Comparator, é so ir adcionando os dadas...

E
Lavieri:
se vc quer Maps ordenados então vc precisa usar TreeMap, e não HashMap... pelo que vc falou, vc quer ordenar o mapa pelo placar, e depois pelo nome, caso o placar seja igual...

1° lugar o seguinte... pra que o MAP ? não entendi a função dele.. qual a função do Integer, Placa ?? ... enfim não vou entrar no merito disso... c vc ker ordenar... então seria assim

vc precisa comparar o value e não a key, então vai ter q fazer um comparator 1 pouco complicado... veja abaixo como seria...

private static class CompararPlacars implements Comparator<Integer> {
        
        private Map<Integer,Placar> placar;
        
        public void setPlacar(Map<Integer,Placar> placar) {
            this.placar = placar;
        }
        
        public int compare(Integer o1, Integer o2) {
            Placar p1 = placar.get(o1);
            Placar p2 = placar.get(o2);
            int result = p1.getResultado().compareTo(p2.getResultado()); //compara os resultados
            if (result == 0) //se o resultado for igual
                result = p1.getJogador().getNome().compareTo(p2.getJogador().getNome()); //compara os nomes
            return result;
        }
    }

ai vai ter q falar para o comparator quem é o map, se não fica impossivel descobrir os placares, já que a ordem de um Map é feito pela KEY e não pelo value...

CompararPlacars compara = new CompararPlacars();
        TreeMap<Integer,Placar> records = new TreeMap<Integer, Placar>(compara);
        compara.setPlacar(records);

Criado assim o meu TreeMap, ele vai ser ordenado automaticamente a cada entrada... vai sempre se manter na ordem especificada pelo Comparator, é so ir adcionando os dadas...

Ae, vlw pela ajuda, ja deu uma clareada nas idéias, mas eu preciso fazer tudo dentro na classe records, eu falei errado, é com treemap mesmo que tenho que usar.

Mas é que nem acabei de falar, a ordenação e tudo tem quer ser dentro da classe records. Pois o professor flw as classes que deveriamos ter. E que naum era para usar outras classes alem das que ele passou.

T

Ele não disse que você não pode usar uma classe anônima (por definição, as classes anônimas não têm nomes, e portanto não estão na lista de classes que seu professor deixou usar.) Além disso, Comparator é uma interface, não uma classe, portanto seu professor tem de deixar usar isso.

Em vez de

CompararPlacars compara = new CompararPlacars();
...new TreeMap (compara);

você tem de usar:

... new TreeMap (new Comparator<Integer>() {
     public int compare(Integer o1, Integer o2) {  
         Placar p1 = placar.get(o1);  
         Placar p2 = placar.get(o2);  
         int result = p1.getResultado().compareTo(p2.getResultado()); //compara os resultados  
         if (result == 0) //se o resultado for igual  
             result = p1.getJogador().getNome().compareTo(p2.getJogador().getNome()); //compara os nomes  
         return result;  
     }  
});
E

Desculpe a ignorancia, mas como a minha classe placar tem que ficar, ela fica como esta ou tenho que altera-la?
Pois nessa parte aqui

Placar p1 = placar.get(o1); Placar p2 = placar.get(o2); } }); [/quote]

fala que eu naum tenho o metodo get na placar.
Outra duvida, na classe records terei que usar algum outro tipo de coleção ou apenas o treemap? Se for somente o treemap, na medida que eu for inserindo nele, ele ja insere ordenado?

Tem como alguem me dar um pequeno exemplo como eu faria para inserir um placar no records, e depois como eu obter os records separando o nome do jogador que vai ser mostrado em um label e a pontuação em outro label.

E

up

B

edileyoliveira:
Desculpe a ignorancia, mas como a minha classe placar tem que ficar, ela fica como esta ou tenho que altera-la?
Pois nessa parte aqui

Placar p1 = placar.get(o1);  
         Placar p2 = placar.get(o2);  
     }  
});

fala que eu naum tenho o metodo get na placar.


placar nesse caso seria uma Collection, não um Placar.

edileyoliveira:

Outra duvida, na classe records terei que usar algum outro tipo de coleção ou apenas o treemap? Se for somente o treemap, na medida que eu for inserindo nele, ele ja insere ordenado?

TreeMaps já inserem ordenado.

ViniGodoy

Não fique upando tópicos!

No lugar, que tal fornecer mais detalhes do que você tentou fazer com as dicas dos colegas?

ViniGodoy

O problema é que você está ordenando um mapa. O mapa exige uma chave e um valor.

Sua chave poderia ser a pontuação, e o valor o nome do indivíduo. O problema é que duas pessoas não poderiam ter a mesma pontuação no placar, o que não faz sentido em nenhum jogo.

A classe pontuação contém os dois, nome e valor. Ela por sí só é uma entrada independente e , se for usada como chave de um map, ela não mapearia valor nenhum. Então, o ideal seria colocar um Set e não um Map. O TreeSet, assim como o TreeMap, já é uma lista ordenada de valores.

Observe o exemplo:
import java.util.SortedSet;
import java.util.TreeSet;

public class Teste {
    private static SortedSet<Escore> placar = new TreeSet<Escore>();

    public static void main(String[] args) throws Exception {
        // Pontuação baseada no número de posts até eu escrever
        // esse código
        placar.add(new Escore("edileyoliveira", 48));
        placar.add(new Escore("ViniGodoy", 5800));
        placar.add(new Escore("Bruno Laturner", 1746));

        // Imprime a pontuação
        imprimirPlacar();

        // Adicionamos mais um ao placar
        placar.add(new Escore("thingol", 15022));

        // Imprime a pontuação
        imprimirPlacar();
    }

    private static void imprimirPlacar() {
        System.out.println("PLACAR");
        System.out.println("------");
        for (Escore s : placar) {
            System.out.printf("%d - %s", s.getPontuacao(), s.getNome());
            System.out.println();
        }
        System.out.println();
        System.out.printf("HI-SCORE: %d - %s", placar.first().getPontuacao(),
                placar.first().getNome());
        System.out.println();
        System.out.println();
    }
}

class Escore implements Comparable<Escore> {
    private String nome;
    private int pontuacao;

    public Escore(String nome, int pontuacao) {
        super();
        this.nome = nome;
        this.pontuacao = pontuacao;
    }

    public String getNome() {
        return nome;
    }

    public int getPontuacao() {
        return pontuacao;
    }

    public int compareTo(Escore o) {
        // Ordenamos pela pontuação em ordem decrescente.
        // Caso a pontuação seja igual, usamos como segundo critério o nome, 
        // em ordem crescente.
        int diff = o.pontuacao - pontuacao;
        return diff == 0 ? nome.compareTo(o.nome) : diff;
    }
}
E

ViniGodoy:
O problema é que você está ordenando um mapa. O mapa exige uma chave e um valor.

Sua chave poderia ser a pontuação, e o valor o nome do indivíduo. O problema é que duas pessoas não poderiam ter a mesma pontuação no placar, o que não faz sentido em nenhum jogo.

A classe pontuação contém os dois, nome e valor. Ela por sí só é uma entrada independente e , se for usada como chave de um map, ela não mapearia valor nenhum. Então, o ideal seria colocar um Set e não um Map. O TreeSet, assim como o TreeMap, já é uma lista ordenada de valores.

Ae Vini…obrigado por tentar me ajudar, mas eu preciso mesmo que seje um map, pois o professor flw que tem q ser um map.
Ele disse que eu teria que usar outra coleção e um map para ordenar, e que a ordenação que era para colocar os nomes de quem tinha a mesma pontuação em ordem alfabetica.
A juda que vcs estao me dando, esta clareando e muito minhas ideias, mas no exemplos vcs me mostraram como montar o treemap e como fazer a ordenação. Mas como sou iniciante em java e o professor não falou nd de como trabalhar com map, apenas flw q deveriamos usar e pronto. E eu soh sei trabalhar com lists, mas nd.
Eu tenho duvidas com farei para inserir o placar na records, naum sei se tenho que inserir primeiro na outra coleção para dpois jogar pro treemap, ou se eh o inverso. e tb naum sei como obter os records separando o nome da pontuação para poder jogar em labels ou textfilds separadados.
E tb tenho me limitar somente dentro das Classes Records, Placar e RecordsVIEW, fora as outras do jogo, mas toda a parte de records tem que ser nas tres.

Vcs me desculpem, mas estou começando agora em java, e nao tenho a mesma facilidade de vcs para entender as coisas, mesmo que sejam coisas novas, vc pelo menos ja tem facildade em java, ja eu não.

Eu pretento continuar no mundo java, sei que vai ser um longo caminho, mas preciso de um empurrao para eu começar ententer melhor.
O basico basico, ja sei até bem, mas agora o professor mudou muito o rumo, começando a trabalhar com MVC com Swing e coleções, com isso to meio perdido.

Conto com ajuda e compreenção de vcs.

ViniGodoy

edileyoliveira:
Ae Vini…obrigado por tentar me ajudar, mas eu preciso mesmo que seje um map, pois o professor flw que tem q ser um map.
Ele disse que eu teria que usar outra coleção e um map para ordenar, e que a ordenação que era para colocar os nomes de quem tinha a mesma pontuação em ordem alfabetica.

Nesse caso, faça um map de um placar para nada… Veja o exemplo abaixo:

import java.util.SortedMap;
import java.util.TreeMap;

public class Teste {
    private static SortedMap<Escore, String> placar = new TreeMap<Escore, String>();

    public static void main(String[] args) throws Exception {
        // Pontuação baseada no número de posts até eu escrever
        // esse código
        placar.put(new Escore("edileyoliveira", 48), "");
        placar.put(new Escore("ViniGodoy", 5800), "");
        placar.put(new Escore("Bruno Laturner", 1746), "");

        // Imprime a pontuação
        imprimirPlacar();

        // Adicionamos mais um ao placar
        placar.put(new Escore("thingol", 15022), "");

        // Imprime a pontuação
        imprimirPlacar();
    }

    private static void imprimirPlacar() {
        System.out.println("PLACAR");
        System.out.println("------");
        for (Escore s : placar.keySet()) {
            System.out.printf("%d - %s", s.getPontuacao(), s.getNome());
            System.out.println();
        }
        System.out.println();
        System.out.printf("HI-SCORE: %d - %s", placar.firstKey().getPontuacao(),
                placar.firstKey().getNome());
        System.out.println();
        System.out.println();
    }
}

class Escore implements Comparable<Escore> {
    private String nome;
    private int pontuacao;

    public Escore(String nome, int pontuacao) {
        super();
        this.nome = nome;
        this.pontuacao = pontuacao;
    }

    public String getNome() {
        return nome;
    }

    public int getPontuacao() {
        return pontuacao;
    }

    public int compareTo(Escore o) {
        // Ordenamos pela pontuação
        int diff = o.pontuacao - pontuacao;
        return diff == 0 ? nome.compareTo(o.nome) : diff;
    }
}
E

Kra, muito obrigado, graças ao seu exemplo consegui fazer e tah rodando que eh uma beleza, eu soh naum consegui entender o funcionamento do metodos compareTo da classe Escore, e desse for for (Escore s : placar.keySet()) tem como vc dar um explicada.

Criado 12 de abril de 2009
Ultima resposta 15 de abr. de 2009
Respostas 11
Participantes 5