2013-06-13 6 views
9

Also bin ich sehr neu in Java und als solche kämpfe ich mich durch eine Übung, indem ich eines meiner Python-Programme in Java umwandle.Java Wie man die Top 10 Elemente basierend auf dem Wert in einer HashMap zurückgibt

Ich habe in ein Problem laufen, wo ich das Verhalten zu wiederholen Ich versuche, aus Python im Folgenden nur die sortierten Schlüssel zurück (von Werten), die Werte:

popular_numbers = sorted(number_dict, key = number_dict.get, reverse = True) 

In Java, ich habe Ich habe ein bisschen geforscht und noch keine einfache Probe für ein n00b wie mich oder eine vergleichbare Methode gefunden. Ich habe Beispiele gefunden, die Guava zum Sortieren verwenden, aber die Sortierung scheint eine nach Schlüsseln sortierte HashMap zu ergeben.

Zusätzlich zu den oben genannten, eine der anderen schönen Dinge über Python, die ich nicht in Java gefunden habe, ist die Fähigkeit, leicht eine Teilmenge der sortierten Werte zurückgeben. In Python kann ich folgende einfach tun:

print "Top 10 Numbers: %s" % popular_numbers[:10] 

In diesem Beispiel number_dict ist ein Wörterbuch von Schlüssel-Wert-Paaren in dem Schlüssel für Zahlen 1..100 und der Wert ist die Anzahl der Male der Zahl (key) eintritt:

Top 10 Zahlen:

for n in numbers: 
if not n == '': 
    number_dict[n] += 1 

Das Endergebnis etwas sein würde, [ '27', '11', '5', '8', '16', '25 ',' 1 ',' 24 ',' 32 ', ' 20 ']

Um zu klären, in Java habe ich erfolgreich eine HashMap erstellt, habe ich erfolgreich Zahlen untersucht und die Werte des Schlüssel, Wert-Paares erhöht. Ich bin jetzt bei der Sortierung fest und gebe die obersten 10 Zahlen (Schlüssel) basierend auf Wert zurück.

+3

Gibt es einen Grund, 'HashMap' zu verwenden, zumal Sie sortieren müssen? – Zong

+0

Haben Sie darüber nachgedacht, eine Baumkarte anstelle einer Hash-Karte zu verwenden? – BlackHatSamurai

+0

Mögliches Duplikat: http://stackoverflow.com/questions/780541/how-to-sort-hash-map, http://stackoverflow.com/questions/8119366/sorting-hashmap-by-values ​​ – BlackHatSamurai

Antwort

0

Ihre Karte Unter der Annahme, so etwas wie diese definiert ist und dass Sie auf Werte sortieren:

HashMap<Integer, Integer> map= new HashMap<Integer, Integer>(); 
//add values 
Collection<Integer> values= map.values(); 
ArrayList<Integer> list= new ArrayList<Integer>(values); 
Collections.sort(list); 

Jetzt drucken, um die ersten Top-10-Elemente der Liste.

for (int i=0; i<10; i++) { 
    System.out.println(list.get(i)); 
} 

Die Werte in der Karte sind nicht wirklich sortieren, weil die HashMap überhaupt nicht sortiert ist (es die Werte in dem Eimer speichert auf der Grundlage der hashCode des Schlüssels). Dieser Code zeigt nur 10 kleinste Elemente in der Karte an.

EDIT sortieren, ohne die Schlüssel-Wert-Paare zu verlieren:

//sorted tree map 
TreeMap<Integer, Integer> tree= new TreeMap<>(); 

//iterate over a map 
Iteartor<Integer> it= map.keySet().iterator(); 
while (it.hasNext()) { 
    Integer key= it.next(); 
    tree.put(map.get(key), key); 
} 

Jetzt haben Sie die TreeMap Baum, sortiert und hat Schlüssel-Wert-Paare aus der ursprünglichen Karte umgekehrt, so dass Sie nicht verlieren die Information.

+0

Jetzt haben Sie die Schlüssel-Wert-Paarungen verloren – NullUserException

+0

Diese sortiert nach den Werten, aber lässt Sie nicht leicht nachschlagen, um zu sehen, auf welchen Schlüssel sie verwiesen ... – chessbot

+0

Ja ist die Bindung verloren, aber es wird funktionieren, wenn Sie brauchen nur die ersten Top 10 Elemente. – AnarchoEnte

10
  1. die entrySet() in eine List der Karte Put.
  2. Diese Liste mit Collections.sort und Comparator sortieren, die basierend auf ihren Werten Entry s sortiert.
  3. Verwenden Sie die subList(int, int) Methode von List, um eine neue Liste mit den Top 10 Elementen abzurufen.

Ja, es wird viel ausführlicher als Python sein :)

+0

Ja, das ist der Weg zu gehen. Aber was war der Sinn der Verwendung von HashMap? Vor allem, wenn das Ergebnis nach * value * geordnet ist? Ich weiß nicht, was das OP macht ... – Zong

0

Versuchen Sie die nächste:

public static void main(String[] args) { 

    // Map for store the numbers 
    Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 

    // Populate the map ... 

    // Sort by the more popular number 
    Set<Entry<Integer, Integer>> set = map.entrySet(); 
    List<Entry<Integer, Integer>> list = new ArrayList<>(set); 
    Collections.sort(list, new Comparator<Entry<Integer, Integer>>() { 
     @Override 
     public int compare(Entry<Integer, Integer> a, 
       Entry<Integer, Integer> b) { 
      return b.getValue() - a.getValue(); 
     } 
    }); 


    // Output the top 10 numbers 
    for (int i = 0; i < 10 && i < list.size(); i++) { 
     System.out.println(list.get(i)); 
    } 

} 
+0

Es wäre besser, 'b.getValue(). CompareTo (a.getValue())' im Vergleich zu verwenden. Das Beispiel des OP verwendet Integer, aber wenn sie sich dafür entscheiden, einige Fließkommazahlen zu setzen, würde nur das Ändern der Typen diesen Code durchbrechen. – Zong

+0

Der 'Wert' ist die ** Popularität ** einer Zahl (die Zahl kann schweben). Mit anderen Worten, die ** Häufigkeit **. –

+0

Okay, ich sehe, dass es in diesem Fall nur ganze Zahlen sein wird. Trotzdem würde ich bei meinem Vorschlag bleiben. – Zong

0

Guava Multiset ein großer fit für Ihren Anwendungsfall ist, und Ihre HashMap schön ersetzen würde . Es ist eine Sammlung, die die Anzahl der Vorkommen jedes Elements zählt.

Multisets hat eine Methode copyHighestCountFirst, die eine unveränderliche Multiset nach Anzahl zurückgibt.

Jetzt sind einige Code:

Multiset<Integer> counter = HashMultiset.create(); 
//add Integers 
ImmutableMultiset<Integer> sortedCount = Multisets.copyHighestCountFirst(counter); 
//iterate through sortedCount as needed 
0

Verwenden Sie ein SortedMap, rufen values(). Die Dokumente zeigen Folgendes:

The collection's iterator returns the values in ascending order of the corresponding keys

Solange Ihr Komparator geschrieben richtig können Sie nur über die ersten n Schlüssel iterieren

1

Mit Java 8+, um die ersten 10 Elemente eines bekommen Liste der intergers:

list.stream().sorted().limit(10).collect(Collectors.toList()); 

Um die ersten 10 Elemente einer Karte der Schlüssel, die ganze Zahlen sind:

map.keySet().stream().sorted().limit(10).collect(Collectors.toMap(Function.identity(), map::get)); 
Verwandte Themen