Сортированная карта не выводит отсортированный.Я понимаю карты. - PullRequest
2 голосов
/ 14 февраля 2012

Я читал на картах и ​​понимаю некоторые различия в древовидных картах и ​​хэш-сортированных картах. Я пытался получить карту для сортировки при выводе.

Что мне нужно было сделать, это:

  1. Возьми текстовый файл и прочитай по содержанию.
  2. Разбейте его на отдельные слова. Используйте слова в качестве ключа, а значение - сколько раз key встречается в текстовом файле.
  3. Если слово находится в конце предложения, я должен сделать его отдельным ключом. Например, my и my. - это две отдельные клавиши.

Моя проблема в том, что независимо от того, объявляю ли я его как дерево, хэш или отсортированную карту, я не могу заставить его выводить / перебирать упорядоченным способом. Сначала я хотел, чтобы он выводился с наибольшим значением, но я даже не могу получить его с ключом в любом порядке.

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 голосов
/ 14 февраля 2012

Ваша карта отсортирована по алфавиту, а не по количеству вхождений.Вам нужно постобработать карту после первоначального разбора.Я бы предложил:

  1. Разобрать файл в HashMap<String, Integer>
  2. Перебрать HashMap и добавить элементы в TreeMap<Integer, Set<String> > (см. Ниже).
  3. Выведите TreeMap.

. Вы можете выполнить шаг 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, вы сортируете слова с одинаковым количеством вхождений в алфавитном порядке.мог бы использовать любой другой Set или List, хотя.

Для нисходящего порядка в шаге 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));

Это должно сделать это.

0 голосов
/ 14 февраля 2012

Map - это своего рода грязная абстракция для такого рода вещей, но я собираюсь выбросить Multiset от Guava как способ решения этого варианта использования, так как он специально разработан для «подсчет событий».

В частности,

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

возвращает Multiset, который перебирает элементы в порядке убывания частоты в listOfWords.

Кстати, есть много вопросов по SO, относящихся к упорядочению карт по значениям вместо ключей, но я предпочитаю это решение .

0 голосов
/ 14 февраля 2012

Это документация для TreeMap, взятая из Javadoc:


public class TreeMap extends AbstractMap
   implements NavigableMap, Cloneable, Serializable

A Red-Black tree based NavigableMap implementation. <b>The map is sorted according 
to the natural ordering of its keys</b>, 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

Как видите, перебор ключей карты дает упорядоченный результат. Этот порядок определяется естественным порядком строки. К сожалению, вы не можете реализовать SortedMap, который сортирует по значениям, что, как я полагаю, вы хотите сделать. Однако вы можете отсортировать записи на карте за ее пределами. Подробности смотрите в этом другом сообщении SO: TreeMap сортировка по значению .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...