2014-10-31 18 views
6

Ich versuche, eine Karte basierend auf Worthäufigkeit (d. H. Basierend auf Wert) zu sortieren. Dafür habe ich Komparator überschrieben und an TreeMap übergeben, aber ich bekomme diese seltsame Ausgabe.Beim Sortieren der Karte basierend auf dem Wert fehlen einige Werte. Was verursacht dieses seltsame Verhalten?

public class WordFrequency { 
    public static String sentence = "one three two two three three four four four"; 
    public static Map<String, Integer> map; 

    public static void main(String[] args) { 
     map = new HashMap<>(); 
     String[] words = sentence.split("\\s"); 

     for (String word : words) { 
      Integer count = map.get(word); 
      if (count == null) { 
       count = 1; 
      } else { 
       ++count; 
      } 
      map.put(word, count); 
     } 

     Comparator<String> myComparator = new Comparator<String>() { 

      @Override 
      public int compare(String s1, String s2) { 
       if (map.get(s1) < map.get(s2)) { 
        return -1; 
       } else if (map.get(s1) > map.get(s2)) { 
        return 1; 
       } else { 
        return 0; 
       } 
      } 

     }; 
     SortedMap<String, Integer> sortedMap = new TreeMap<String, Integer>(myComparator); 
     System.out.println("Before sorting: " + map); 
     sortedMap.putAll(map); 
     System.out.println("After Sorting based on value:" + sortedMap); 

    } 
} 

Ausgang:

Before sorting: {two=2, one=1, three=3, four=3} 
After sorting based on value:{one=1, two=2, three=3} 

Erwartete Ausgabe:

{one=1, two=2, four=3,three=3} 
+0

Was ist komisch daran? –

+0

Möglicherweise TreeMap nicht erlaubt Duplikate –

+0

@SotiriosDelimanolis vier = 3 fehlt nach dem Sortieren –

Antwort

5

Ihre compare-Methode entspricht nicht dem Vertrag der Map-Schnittstelle, da sie Werte anstelle von Schlüsseln vergleicht. Ihre Implementierung bewirkt, dass zwei Schlüssel mit demselben Wert als derselbe Schlüssel gelten. Daher enthält Ihr sortedMap nicht die Taste "vier", die den gleichen Wert wie die Taste "drei" hat.

Beachten Sie, dass die Bestellung durch einen Baum Karte, wie jede sortierte Karte gehalten wird, und ob oder ob nicht eine explizite Komparator vorgesehen ist, muss mit equals konsistent sein, wenn diese sortierten Karte korrekt ist, um die Karte Schnittstelle zu implementieren. (Vergleiche oder Vergleicher für eine genaue Definition von konsistent mit equals.) Dies ist so, weil die Map-Schnittstelle in der Gleichheitsoperation definiert ist, aber eine sortierte Map alle Schlüsselvergleiche mithilfe der compareTo (oder compare) -Methode durchführt. so zwei Schlüssel, die durch diese Methode gleich sind, sind vom Standpunkt der sortierten Karte gleich. Das Verhalten einer sortierten Karte ist gut definiert, selbst wenn ihre Reihenfolge nicht mit Gleichem übereinstimmt. Es entspricht nur nicht dem allgemeinen Vertrag der Map-Schnittstelle.

TreeMap reference

Sie können dieses Problem beheben, indem die Schlüssel zu vergleichen, wenn die Werte gleich sind:

Comparator<String> myComparator = new Comparator<String>() { 

     @Override 
     public int compare(String s1, String s2) { 
      if (map.get(s1) < map.get(s2)) { 
       return -1; 
      } else if (map.get(s1) > map.get(s2)) { 
       return 1; 
      } else { 
       return s1.compareTo(s2); 
      } 
     } 

    }; 

Dies sollte Ihnen eine Leistung von geben:

After sorting based on value:{one=1, two=2, four=3, three=3} 

Seit four<three basierend auf der natürlichen Reihenfolge der Strings.

4

Aufgrund Ihrer compare() ist Werte berücksichtigen nur im Map. Dann hat three=3, four=3 denselben Wert 3. Dann betrachten diese als Duplikate, wenn sie zu hinzufügen.

1

Das ist, weil Ihre Implementierung TreeMap sagt, dass map [drei] und map [vier] im Wesentlichen das gleiche Element sind, weil sie einander gemäß Ihrer Vergleicher "gleich" sind.

Change "return 0" in Vergleicher zu "return s1.compareTo (s2)", und Sie werden

Before sorting: {two=2, one=1, three=3, four=3} 
After Sorting based on value:{one=1, two=2, four=3, three=3} 

haben (ich glaube, Sie können herausfinden, warum "vier" kommt vor "drei" in diesem Fall)

+0

Danke @mindex Ich habe es herausgefunden. –