Количество отсортированных слов с использованием Hadoop MapReduce - PullRequest
10 голосов
/ 31 марта 2010

Я очень плохо знаком с MapReduce и завершил пример подсчета слов в Hadoop.

В этом примере он производит несортированный файл (с парами ключ-значение) с количеством слов. Так можно ли отсортировать его по количеству вхождений слов, комбинируя другую задачу MapReduce с предыдущей?

Ответы [ 4 ]

1 голос
/ 10 апреля 2013

В простой программе отображения количества слов программа вывода выводит по словам. Пример вывода может быть:
Яблоко 1
Мальчик 30
Кот 2
Лягушка 20
Зебра 1
Если вы хотите, чтобы вывод был отсортирован по количеству вхождений слов, т.е. в формате ниже
1 яблоко
1 зебра
2 кат
20 лягушка
30 Мальчик
Вы можете создать другую программу MR, используя приведенный ниже маппер и редуктор, где на вход будет вывод, полученный из простой программы подсчета слов.

class Map1 extends MapReduceBase implements Mapper<Object, Text, IntWritable, Text>
{
    public void map(Object key, Text value, OutputCollector<IntWritable, Text> collector, Reporter arg3) throws IOException 
    {
        String line = value.toString();
        StringTokenizer stringTokenizer = new StringTokenizer(line);
        {
            int number = 999; 
            String word = "empty";

            if(stringTokenizer.hasMoreTokens())
            {
                String str0= stringTokenizer.nextToken();
                word = str0.trim();
            }

            if(stringTokenizer.hasMoreElements())
            {
                String str1 = stringTokenizer.nextToken();
                number = Integer.parseInt(str1.trim());
            }

            collector.collect(new IntWritable(number), new Text(word));
        }

    }

}


class Reduce1 extends MapReduceBase implements Reducer<IntWritable, Text, IntWritable, Text>
{
    public void reduce(IntWritable key, Iterator<Text> values, OutputCollector<IntWritable, Text> arg2, Reporter arg3) throws IOException
    {
        while((values.hasNext()))
        {
            arg2.collect(key, values.next());
        }

    }

}
0 голосов
/ 10 декабря 2013

Как вы сказали, одна возможность - написать две работы для этого. Первая работа: Простой пример подсчета слов

Вторая работа: Есть сортировка часть.

Псевдокод может быть:

Примечание: выходной файл, сгенерированный первым заданием, будет вводом для второго задания

    Mapper2(String _key, Intwritable _value){
    //just reverse the position of _value and _key. This is useful because reducer will get the output in the sorted and shuffled manner.
    emit(_value,_key);
    }

    Reduce2(IntWritable valueofMapper2,Iterable<String> keysofMapper2){
//At the reducer side, all the keys that have the same count are merged together.
        for each K in keysofMapper2{
        emit(K,valueofMapper2); //This will sort in ascending order.
        }

    }

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

Job.setComparatorclass(Comparator.class);

Этот компаратор отсортирует значения в порядке убывания перед отправкой на сторону редуктора. Поэтому на редукторе вы просто излучаете значения.

0 голосов
/ 28 апреля 2010

В Hadoop сортировка выполняется между фазами Map и Reduce. Один из подходов к сортировке по слову встречается в том, чтобы использовать собственный групповой компаратор, который ничего не группирует; следовательно, каждый призыв к уменьшению - это просто ключ и одно значение.

public class Program {
   public static void main( String[] args) {

      conf.setOutputKeyClass( IntWritable.class);
      conf.setOutputValueClass( Text.clss);
      conf.setMapperClass( Map.class);
      conf.setReducerClass( IdentityReducer.class);
      conf.setOutputValueGroupingComparator( GroupComparator.class);   
      conf.setNumReduceTasks( 1);
      JobClient.runJob( conf);
   }
}

public class Map extends MapReduceBase implements Mapper<Text,IntWritable,IntWritable,Text> {

   public void map( Text key, IntWritable value, OutputCollector<IntWritable,Text>, Reporter reporter) {
       output.collect( value, key);
   }
}

public class GroupComaprator extends WritableComparator {
    protected GroupComparator() {
        super( IntWritable.class, true);
    }

    public int compare( WritableComparable w1, WritableComparable w2) {
        return -1;
    }
}
0 голосов
/ 06 апреля 2010

Выходные данные из примера wordcount Hadoop MapReduce сортируются по ключу. Таким образом, вывод должен быть в алфавитном порядке.

С помощью Hadoop вы можете создавать свои собственные ключевые объекты, реализующие интерфейс WritableComparable, позволяющий переопределить метод compareTo. Это позволяет вам контролировать порядок сортировки.

Чтобы создать вывод, отсортированный по количеству вхождений, вам, вероятно, потребуется добавить еще одно задание MapReduce для обработки вывода первого, как вы сказали. Эта вторая работа была бы очень простой, возможно, даже не требующей фазы сокращения. Вам просто нужно реализовать свой собственный ключевой объект Writable для переноса слова и его частоты. Пользовательская запись выглядит примерно так:

 public class MyWritableComparable implements WritableComparable {
       // Some data
       private int counter;
       private long timestamp;

       public void write(DataOutput out) throws IOException {
         out.writeInt(counter);
         out.writeLong(timestamp);
       }

       public void readFields(DataInput in) throws IOException {
         counter = in.readInt();
         timestamp = in.readLong();
       }

       public int compareTo(MyWritableComparable w) {
         int thisValue = this.value;
         int thatValue = ((IntWritable)o).value;
         return (thisValue < thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
       }
     }

Я взял этот пример из здесь .

Вы, вероятно, также должны переопределить hashCode, equals и toString.

...