2014-09-17 7 views
5

Ho un HashMap come questo:In Java, mappa sorta di hash per la sua key.length()

HashMap<String,Integer> map = new HashMap<String,Integer>(); 
map.put("java",4); 
map.put("go",2); 
map.put("objective-c",11); 
map.put("c#",2); 

Ora voglio ordinare questa mappa per la sua lunghezza della chiave, se due chiavi di lunghezza sono uguali (ad esempio, vai C# entrambi lunghezza 2), quindi ordinati per ordine alphba. modo che il risultato mi aspetto di ottenere è qualcosa di simile:

risultato stampato: Objective-C, 11 Java, 4 C#, 2 go, 2

qui è la mia attamp, ma doesnt funziona affatto ...

 HashMap<String,Integer> map = new HashMap<String,Integer>(); 
      map.put("java",4); 
      map.put("go",2); 
      map.put("objective-c",11); 
      map.put("c#",2); 

     Map<String,Integer> treeMap = new TreeMap<String, Integer>(
       new Comparator<String>() { 
        @Override 
        public int compare(String s1, String s2) { 
         return s1.length().compareTo(s2.length()); 
        } 
       } 
     ); 

in realtà il metodo 'compareTo' compare in rosso (non essere in grado di compilare) .... per favore qualcuno mi aiuti con qualche esempio di codice ... io sono un po 'di confusione con come utilizzare la classe di confronto per personalizzare il compa re oggetto ...

risposta

12

Il compilatore si lamenta perché non si può chiamare compareTo su un int. Il modo corretto per ordinare la mappa è la seguente:

Map<String, Integer> treeMap = new TreeMap<String, Integer>(
    new Comparator<String>() { 
     @Override 
     public int compare(String s1, String s2) { 
      if (s1.length() > s2.length()) { 
       return -1; 
      } else if (s1.length() < s2.length()) { 
       return 1; 
      } else { 
       return s1.compareTo(s2); 
      } 
     } 
}); 

Le prime due condizioni confrontano le lunghezze dei due String s e restituiscono un positivo o un numero negativo di conseguenza. La terza condizione dovrebbe confrontare lessicograficamente il String se le loro lunghezze sono uguali.

2

perché length() non definisce il metodo compareTo perché si vede l'errore. Per correggere esso uso Integer.compare(s1.length(), s2.length()); codice aggiornato sotto

import java.util.Comparator; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.TreeMap; 

public class Test { 

    public static void main(String[] args) { 

     HashMap<String,Integer> map = new HashMap<String,Integer>(); 
     map.put("java",4); 
     map.put("go",2); 
     map.put("objective-c",11); 
     map.put("c#",2); 


     Map<String,Integer> treeMap = new TreeMap<String, Integer>(
       new Comparator<String>() { 
        @Override 
        public int compare(String s1, String s2) { 
         return Integer.compare(s1.length(), s2.length()); 
        } 
       } 
     ); 

     treeMap.putAll(map); 

     System.out.println(treeMap); 
    } 
} 
+1

quando si esegue il codice, il risultato è {C# = 2, java = 4, Objective-C = 11}. la domanda è dove è il "go", 2? –

+0

È dovuto al fatto che TreeMap sta usando Comparator e il comparatore è definito per trattare 2 stringhe della stessa lunghezza uguale. Dato che OP stava giocando con TreeMap, ho esteso la sua risposta per correggere solo la parte Comparator. – sol4me

+0

oh cool cosa ne pensi della mia risposta? dal momento che l'op non ha menzionato che l'uso di treemap è obbligatorio, ho usato un altro stile –

-1

Il comparatore dovrebbe essere:

new Comparator<String>() { 
    @Override 
    public int compare(String s1, String s2) { 
     return Integer.compare(s1.length(), s2.length()); 
    } 
} 
+3

Non funziona. Se le due stringhe hanno la stessa lunghezza e utilizzano una TreeMap per ordinare, considereranno le chiavi String della stessa lunghezza dei duplicati e le rimuoveranno. –

4

Si chiama String#length(), che restituisce un primitivo int. È necessario il metodo statico Integer.compare(int,int). Se siete su Java 8, è possibile risparmiare un sacco di battitura:

Map<String,Integer> treeMap = new TreeMap<>(
     Comparator.comparingInt(String::length) 
        .thenComparing(Function.identity())); 
+0

signore, il tuo out è {}? –

+1

Il mio codice non tenta alcun output, ma se stai chiedendo della rappresentazione String di una mappa vuota, hai ragione. –

+0

Ho postato questa domanda. se puoi rispondere a http://stackoverflow.com/questions/25905445/apply-distinct-function-on-treemap –

1

Se si utilizza il TreeMap è non è obbligatorio

explantion: Definire un Comaprator, e il prossimo passo, definire un elenco in modo che possiamo aggiungere tutte le voci della mappa in un elenco.Alla fine, ordinare l'elenco per definito Comaprator

Codice:

Comparator<Map.Entry<String,Integer>> byMapValues = 
     (Map.Entry<String,Integer> left, Map.Entry<String,Integer> right) ->left.getValue().compareTo(right.getValue()); 

List<Map.Entry<String,Integer>> list = new ArrayList<>(); 
list.addAll(map.entrySet()); 
Collections.sort(list, byMapValues); 
list.forEach(i -> System.out.println(i)); 

uscita:

c#=2 
go=2 
java=4 
objective-c=11 

Nota: ottenere ordinati secondo il numero

se ci è necessario fare comparis in base alla chiave, è possibile utilizzare la seguente riga.

Comparator<Map.Entry<String,Integer>> byMapKeys = 
      (Map.Entry<String,Integer> left, Map.Entry<String,Integer> right) -> left.getKey().compareTo(right.getKey()); 
1
 public int compare(String o1, String o2) { 
      return o1.length() == o2.length() ? o1.compareTo(o2) : o1.length() - o2.length(); 
     }