Лучший способ достичь этого - вторичный сорт. Вам нужно отсортировать оба ключа (в номерах вашего номера) и значения (в именах файлов вашего случая). В Hadoop выход картографа сортируется только по клавишам.
Это может быть достигнуто с помощью комбинированного ключа: ключ, который представляет собой комбинацию обоих чисел и имен файлов. Напр. для первой записи ключ будет (23, fileA), а не просто (23).
Вы можете прочитать о среднем рода здесь: https://www.safaribooksonline.com/library/view/data-algorithms/9781491906170/ch01.html
Вы также можете пройти в раздел "Secondary Сортировка", в "Hadoop The Definitive Guide" книги.
Для простоты я написал программу для достижения того же.
В этой программе ключи сортируются по умолчанию картографами. Я написал логику для сортировки значений на стороне редуктора. Поэтому он заботится о сортировке как ключей, так и значений и создает желаемый результат.
Ниже приводится программа:
package com.myorg.hadooptests;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
import java.util.*;
public class SortedValue {
public static class SortedValueMapper
extends Mapper<LongWritable, Text , Text, IntWritable>{
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] tokens = value.toString().split(" ");
if(tokens.length == 2) {
context.write(new Text(tokens[1]), new IntWritable(Integer.parseInt(tokens[0])));
}
}
}
public static class SortedValueReducer
extends Reducer<Text, IntWritable, IntWritable, Text> {
Map<String, ArrayList<Integer>> valueMap = new HashMap<String, ArrayList<Integer>>();
public void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
String keyStr = key.toString();
ArrayList<Integer> storedValues = valueMap.get(keyStr);
for (IntWritable value : values) {
if (storedValues == null) {
storedValues = new ArrayList<Integer>();
valueMap.put(keyStr, storedValues);
}
storedValues.add(value.get());
}
Collections.sort(storedValues);
for (Integer val : storedValues) {
context.write(new IntWritable(val), key);
}
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "CompositeKeyExample");
job.setJarByClass(SortedValue.class);
job.setMapperClass(SortedValueMapper.class);
job.setReducerClass(SortedValueReducer.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(IntWritable.class);
job.setOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, new Path("/in/in1.txt"));
FileOutputFormat.setOutputPath(job, new Path("/out/"));
System.exit(job.waitForCompletion(true) ? 0:1);
}
}
Mapper Логика:
- Разбираем каждую строку. Предполагается, что ключ и значение разделяются пустым символом ("").
- Если строка содержит 2 жетона, она испускает (имя файла, целочисленное значение). Напр. для первой записи он испускает (fileA, 23).
Редуктор Логика:
Это ставит (ключ, значение) пар в HashMap, где ключ это имя файла и значение представляет собой список целых чисел для этого файла. Напр. для файлаA сохраненные значения будут 23, 34 и 35
Наконец, он сортирует значения для определенного ключа и для каждого значения испускает (значение, ключ) из редуктора. Напр. для FiLea, выход записи: (23, FiLea), (34, FiLea) и (35, FiLea)
Я запустил эту программу для следующего входа:
34 fileB
35 fileA
60 fileC
60 fileA
23 fileA
я получил следующий результат:
23 fileA
35 fileA
60 fileA
34 fileB
60 fileC
Вы имеете в виду, что вы хотите, чтобы и номера, и имена файлов были отсортированы. Напр. «23 файлаA», «35 файлов», «60 файлов», «34 файла», «60 файлов»? Здесь все записи «fileA» отображаются сначала в отсортированном порядке, а затем в файле B, а затем в filcC. Это то, что вы хотите? Просьба уточнить. Исходя из этого, я могу видеть, могу ли я предоставить answe –
Оба числа и имена файлов должны сортироваться, но не отдельно. Номера и имена файлов должны быть смешаны вместе, как пример выше. – Dobby
Вы можете сделать это с помощью составных клавиш или с использованием вторичной сортировки. – YoungHobbit