Como ordenar um Map pelo valor em ves da chave

EDIT: Ou seja, pode tentar isso:
Map<K, V> map = …;
Collections.sort(map.values());[/quote]

Isso não faz nada. Veja a parte em itálico. A coleção de valores é uma view, o que significa que o mapa não mantém uma coleção de valores. O que ele mantém é uma coleção de key-valor chamada entry (Map.Entry). Repare que a iteração dos valores é na ordem das chaves. ser backed significa que a alteração de Map.Entry significa a alteração da coleção e da iteração ( existe um CocurrentModificationException) e não que alteração em map.values() altera o mapa. Mesmo que o sort ordenasse a view ( que por definição não afeta o mapa) ele não alteraria as chaves, logo não alteraria o mapa.

Ordenar um mapa pelos valores não é possivel, a menos que implemente o seu próprio mapa.
A realidade é que ordenar um mapa pelos valores representa um erro na modelagem e no uso do mapa em primeiro lugar.
Mas caso seja muito necessário ha que implementar o mapa de novo reorganizando as Map.Entry com uma nova lógica.

[quote=victorwss][quote=ramilani12]Exatamente seria o caso de implementar um Comparator.

Um link que pode te ajudar: http://paaloliver.wordpress.com/2006/01/24/sorting-maps-in-java/[/quote]

Exatamente isso. :smiley: [/quote]
Implementei o exemplo e funciona realmente. Ele ordena os maps pelo valor. :smiley:
Contudo, nem tudo são flores. Se houver mais de uma chave, com o mesmo valor, ela é sobrescrita pelo map seguinte que contém o mesmo valor, mesmo que tenha outra chave…

EDIT: Ou seja, pode tentar isso:
Map<K, V> map = …;
Collections.sort(map.values());[/quote]

Isso não faz nada. Veja a parte em itálico. A coleção de valores é uma view, o que significa que o mapa não mantém uma coleção de valores. O que ele mantém é uma coleção de key-valor chamada entry (Map.Entry). Repare que a iteração dos valores é na ordem das chaves. ser backed significa que a alteração de Map.Entry significa a alteração da coleção e da iteração ( existe um CocurrentModificationException) e não que alteração em map.values() altera o mapa. Mesmo que o sort ordenasse a view ( que por definição não afeta o mapa) ele não alteraria as chaves, logo não alteraria o mapa.

Ordenar um mapa pelos valores não é possivel, a menos que implemente o seu próprio mapa.
A realidade é que ordenar um mapa pelos valores representa um erro na modelagem e no uso do mapa em primeiro lugar.
Mas caso seja muito necessário ha que implementar o mapa de novo reorganizando as Map.Entry com uma nova lógica.
[/quote]

Quero ordernar o map pelo valor para usá-lo numa implementaçãp de um algoritmo de extração de padrões em grafos.

[quote=emanoeltadeu][quote=victorwss][quote=ramilani12]Exatamente seria o caso de implementar um Comparator.

Um link que pode te ajudar: http://paaloliver.wordpress.com/2006/01/24/sorting-maps-in-java/[/quote]

Exatamente isso. :smiley: [/quote]
Implementei o exemplo e funciona realmente. Ele ordena os maps pelo valor. :smiley:
Contudo, nem tudo são flores. Se houver mais de uma chave, com o mesmo valor, ela é sobrescrita pelo map seguinte que contém o mesmo valor, mesmo que tenha outra chave…[/quote]

mas veja nos comentários que há uma solução para isso ele utiliza o compareTo do hashcode

Digamos que você tenha uma classe Aluno com as chaves únicas “id” e “nome”. (Estou considerando que não há homônimos, só para simplificar. Se houver homônimos você não vai poder usar diretamente um SortedMap, como você vai ver mais tarde).

class Aluno {
    public Long id;
    public String nome;
    public Aluno (final Long id_, final String nome_) { id = id_; nome = nome_; }
    public String toString() { return "[" + id + "," + nome + "]"; }
}

Se você quiser ordenar os elementos dessa classe por id ou por nome, precisa criar 2 SortedMaps, um por id, outro por nome.

SortedMap<Long,Aluno> porId = new TreeMap<Long,Aluno>(new Comparator<Aluno>() {
    public int compare (Aluno a1, Aluno a2) {
        return a1.id.compareTo (a2.id);
    }
});

SortedMap<String,Aluno> porNome = new TreeMap<String,Aluno>(new Comparator<Aluno>() {
    public int compare (Aluno a1, Aluno a2) {
        return a1.nome.compareTo (a2.nome);
    }
});

Quando for inserir ou remover um elemento, você precisa inserir ou remover nos dois Maps.

Bom passei por esse problema tbm por isso recomendei aquele link:

Uma solução que encontrei foi esta:

Tenho um map e a chave é um auto-incremento do banco de dados ate ai nenhum problema mas ao ordenar surgiram chaves diferentes mas como mesmos valores, caso compareTo retornar 0 comparo com valor do HashCode

public int compare(Object key, Object key1)
{
		// TODO Auto-generated method stub
		Long id1 = (Long) key;
		Long id2 = (Long) key1;
		Atividade a1 = (Atividade) atividades.get(id1);
		Atividade a2 = (Atividade) atividades.get(id2);
		
	       //Aqui utilizo compareTo do objeto java.util.Date	
               int c = a1.getDataAtividade().compareTo(a2.getDataAtividade()); 
		
		if (c == 0)
		{	
			Integer h1 = new Integer(a1.hashCode());
			Integer h2 = new Integer(a2.hashCode());
			return h1.compareTo(h2);
		}
		
	return c;
	}

sim, utilizei o seguinte método compare e deu certo:

        public int compare(Object key1, Object key2) {
            Integer e1 = (Integer) _data.get(key1);
            Integer e2 = (Integer) _data.get(key2);

            int c = e2.compareTo(e1);

            if (0 != c) return c;
           
            Integer h1 = key1.hashCode(), h2 = key2.hashCode();
            return h2.compareTo(h1);
        }

Comparei o segundo com o primeiro porque quero a ordenação feita de modo decrescente.