Как сортировать численно в фазе случайного перетасовки/сортировки?

Данные выглядят следующим образом: первое поле - это число,

3 ...
1 ...
2 ...
11 ...

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

1 ...
2 ...
3 ...
11 ...

Но hadoop продолжает давать мне это,

1 ...
11 ...
2 ...
3 ...

Как это исправить?

Ответ 1

Предполагая, что вы используете Hadoop Streaming, вам нужно использовать класс KeyFieldBasedComparator.

  • -D mapred.output.key.comparator.class= org.apache.hadoop.mapred.lib.KeyFieldBasedComparator следует добавить в поточную команду

  • Вам нужно указать тип сортировки, требуемый с помощью mapred.text.key.comparator.options. Некоторые полезные: -n: числовая сортировка, -r: обратная сортировка

ПРИМЕР:

Создайте идентификатор и редуктор со следующим кодом

Это mapper.py и reducer.py

#!/usr/bin/env python
import sys
for line in sys.stdin:    
    print "%s" % (line.strip())

Это input.txt

1
11
2
20
7
3
40

Это команда Потоковая передача

$HADOOP_HOME/bin/hadoop  jar $HADOOP_HOME/hadoop-streaming.jar 
-D mapred.output.key.comparator.class=org.apache.hadoop.mapred.lib.KeyFieldBasedComparator 
-D  mapred.text.key.comparator.options=-n 
-input /user/input.txt 
-output /user/output.txt 
-file ~/mapper.py 
-mapper ~/mapper.py 
-file ~/reducer.py 
-reducer ~/reducer.py

И вы получите требуемый вывод

1   
2   
3   
7   
11  
20  
40

ПРИМЕЧАНИЕ:

  • Я использовал простой один ключевой ввод. Если, однако, у вас есть несколько ключей и/или разделов, вам необходимо будет изменить mapred.text.key.comparator.options по мере необходимости. Поскольку я не знаю вашего примера использования, мой пример ограничен этим

  • Требуется сопоставление идентификаторов, так как вам понадобится по крайней мере один картограф для выполнения задания MR.

  • Необходим редуктор идентичности, так как фаза случайной или сортировки не будет работать, если это чистое задание только для карты.

Ответ 2

Сравнитель по умолчанию Hadoop сравнивает ваши ключи на основе типа Writable (точнее WritableComparable), который вы используете. Если вы имеете дело с IntWritable или LongWritable, то он будет сортировать их численно.

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

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

public class MyComparator extends WritableComparator {

        public MyComparator() {
            super(Text.class);
        }

        @Override
        public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {

            try {

                String v1 = Text.decode(b1, s1, l1);
                String v2 = Text.decode(b2, s2, l2);

                int v1Int = Integer.valueOf(v1.trim());
                int v2Int = Integer.valueOf(v2.trim());

                return (v1Int < v2Int) ? -1 : ((v1Int > v2Int) ? 1 : 0);

            }
            catch (IOException e) {
                throw new IllegalArgumentException(e);
            }
        }
    }

В классе класса jobrunner:

Job job = new Job();
...
job.setSortComparatorClass(MyComparator.class);