Каков порядок ввода ключей в методе reduce()

#java #hadoop #mapreduce

#java #hadoop #mapreduce

Вопрос:

У меня есть простой вариант использования. В моем входном файле мне просто нужно рассчитать процентное распределение общего количества слов. Например, word1 присутствует 10 раз, word2 присутствует 5 раз и т.д., А Общее количество слов равно 100, Тогда мне просто нужно отобразить % word1 = 10%, % word2 = 5% и т.д. Поэтому всякий раз, когда я сталкиваюсь со словом, я просто помещаю context.write(word, 1) в map() и в reduce суммирую отдельные подсчеты. Но для вычисления процента нам требуется общее количество слов. Я также вычисляю это.

Следовательно, перед получением ключей для word1 или word2 в reduce я должен получить ключ общего количества слов для вычисления процента для каждого слова. Но при сокращении я получаю этот ключ total words после некоторых других ключей. Следовательно, я не могу вычислить процент.

Я также пытался установить это общее количество в конфигурации map, используя context.getConfiguration().SetFloat(«общее количество»,count); Но в reduce я не могу получить это значение из конфигурации. Он просто возвращает null.

Пожалуйста, добавьте любые предложения.

Спасибо..

Комментарии:

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

2. Кстати, порядок ввода ключей сортируется на основе компаратора по умолчанию. Итак, если это текст, то в лексикографическом порядке. Однако каждый ключ будет использоваться только в одном редукторе, поэтому вы не можете просто вывести общее количество слов в качестве ключа, если хотите, чтобы ваш код работал с несколькими редукторами.

Ответ №1:

Сначала вам нужно переварить ваш документ, вот так:

 class WordCounter {
    Map<String, Integer> totals = new HashMap<String, Integer>();
    int wordCount;

    void digest(String document) {
        for (String word : document.split("\w ")) {
            wordCount  ;
            Integer count = totals.get(word);
            if (count == null)
                totals.put(word, 1);
            else
                totals.put(word,   count);
        }
    }
}
  

Затем вы можете выполнить второй проход по своему документу, делая то, что вам нравится, с собранной вами информацией, возможно, используя что-то вроде этого метода для каждого слова:

 String decorateWithPercent(String word) {
    return word   " ("   (totals.get(word) / wordCount)   "%)";
}
  

Или для печати частот, что-то вроде:

 void printFrequencies() {
    for (Map.Entry<String, Integer> wordCount : totals.entrySet()) {
        System.out.println(wordCount.getKey()   " "   wordCount.getValue());
    }
}
  

Комментарии:

1. Спасибо за ваше предложение. Я хочу реализовать логику в map reduce, используя один проход, поскольку файл, который я хочу отсканировать, составляет 15 ГБ.