排序的地图不输出已排序。我了解地图吗?

时间:2012-02-14 04:33:16

标签: java map

我一直在阅读地图,了解树图和哈希,有序地图的一些差异。我试图在输出时将地图分类。

我需要做的是:

  1. 获取文本文件并阅读内容。
  2. 将其分成单独的单词。使用单词作为键,将值作为txt文件中出现key的次数。
  3. 如果单词在句子的末尾,我将把它作为一个单独的键。例如,mymy.是两个单独的键。
  4. 我的问题是,无论我是将它声明为树,哈希还是有序地图,我都无法以有序的方式输出/迭代。我希望它首先以最高出现值输出,但我甚至无法以任何顺序输出密钥。

    public static Map<String, Integer> createDictionary(String _filename)
    {
        TreeMap<String, Integer> dictionary = new TreeMap<String, Integer>(); // Changed Hash to _______
    
        try {
              FileReader myFileReader=new FileReader(_filename); // File reader stream open
              BufferedReader myBuffReader=new BufferedReader(myFileReader);
    
              String str = "\0";
    
              while (str != null) { // While there are still strings in the file
                  str = myBuffReader.readLine(); // We read a line into the str variable
    
                  if (str != null) { // Make sure its not the last line/EOF 
                      // System.out.println(str); // Used for testing. 
                      StringTokenizer myTokenStr=new StringTokenizer(str," \t"); // Create a StringToken obj from the string
    
                      while (myTokenStr.hasMoreTokens()) {
                          String tokStr = myTokenStr.nextToken(); // Each token is put into an individual string
                          // System.out.println(tokStr);
    
                          if (dictionary.containsKey(tokStr)) {
                              int value = dictionary.get(tokStr); // Add one to the integer value
                              // dictionary.remove(tokStr); // Was doing this way but just using put method works 
                              // dictionary.put(tokStr, value + 1);
                              dictionary.put(tokStr, value + 1);
                          }
                          else {
                              dictionary.put(tokStr, 1); // Add the string as the key with an int value of one for the value
                          }
                      }
                  }
              }
    
              myBuffReader.close(); // Close stream
              myFileReader.close(); // Close stream
          }
          catch (FileNotFoundException e) {
              System.out.println("File Not Found");
          }
          catch (IOException e) { }
    
          // System.out.println(dictionary.entrySet());
    
          return dictionary;
    }
    

3 个答案:

答案 0 :(得分:0)

这是TreeMap的文档,取自它的Javadoc:


public class TreeMap extends AbstractMap
   implements NavigableMap, Cloneable, Serializable

A Red-Black tree based NavigableMap implementation. The map is sorted according 
to the natural ordering of its keys, or by a Comparator provided at map creation
time, depending on which constructor is used.

在您的情况下,键将是字符串,您应该期望迭代将根据其“自然顺序”显示要排序的映射。以下是TreeMap生成的输出示例,该输出由String键和Integer值组成:

Map<String, Integer> map = new TreeMap<String, Integer>();
map.put("Hello", Integer.valueOf(8));
map.put("Abraham", Integer.valueOf(81));
map.put("Smell", Integer.valueOf(-1));
map.put("Carpet", Integer.valueOf(4));
map.put("Sex", Integer.valueOf(23));

for(String key: map.keySet()) {
    System.out.printf("Map entry %s: %d\n", key, map.get(key));
}

输出:

Map entry Abraham: 81
Map entry Carpet: 4
Map entry Hello: 8
Map entry Sex: 23
Map entry Smell: -1

正如您所看到的,迭代地图的键会产生有序的结果。此顺序由String的自然顺序定义。不幸的是, 无法 实现对值进行排序的SortedMap,这是我认为您想要做的事情。但是,您可以在其外部的Map中对条目进行排序。在其他SO帖子中查看更多详细信息:TreeMap sort by value

答案 1 :(得分:0)

您的地图按字母顺序排序,而不是按出现次数排序。您需要在初始解析后对地图进行后处理。我建议:

  1. 将文件解析为HashMap<String, Integer>
  2. 遍历HashMap,并将元素添加到TreeMap<Integer, Set<String> >(见下文)。
  3. 输出TreeMap
  4. 你可以通过以下方式实现第2步:

    TreeMap<Integer, Set<String> > treeMap = new TreeMap<Integer, Set<String> > ();
    for (Map.Entry<String, Integer> entry: hashMap) {
        Set<String> set = treeMap.get(entry.value());
        if (set == null) {
            set = new TreeSet<String>();
            treeMap.put(entry.value(), set);
        }
        set.add(entry.key());
    }
    

    在此处使用TreeSet按字母顺序对具有相同出现次数的字词进行排序,但您可以使用任何其他SetList

    对于步骤3中的降序。:

    for (Map.Entry<Integer, Set<String> > entry: treeMap.descendingMap())
        for (String word: entry.getValue())
            System.out.println(String.format("%d: %s", entry.getKey(), word));
    

    应该这样做。

答案 2 :(得分:0)

对于这类事情,

Map是一种混乱的抽象,但是我要抛弃Guava的Multiset作为解决这个用例的方法,因为它专门用于“计算”事情的发生。“

特别是

return Multisets.copyHighestCountFirst(HashMultiset.copyOf(listOfWords));

返回Multiset,按listOfWords中频率降序的顺序迭代元素。

顺便说一下,关于按而非按键排序地图的问题,有很多问题,但我更喜欢this solution