В те дни, когда я играл с картой-свертка, у меня была подобная мысль, что должна быть некоторая практика или метод, с помощью которого мы можем модифицировать каждое слово в записи и делать все чистящие средства.
Когда мы перечислим весь алгоритм сокращения карты, у нас есть функция отображения, которая разбивает поступающие записи на токены с помощью разделителей (возможно, вы узнаете о них лучше). Теперь попробуем подойти к описанию проблемы, данному вами описательным образом.
Ниже перечислены вещи, которые я буду стараться делать, когда я новичок в Map-Reduce:
> I will probably write a map() method which will split the lines for me
> I will possibly run out of options and write a reduce function
and somehow will be able to achieve my objective
выше практика полностью в порядке, но есть лучший метод, который может помочь вам решить, будет ли или нет вам понадобится функция уменьшения, поэтому у вас будет больше возможностей, чтобы вы могли подумать и полностью сосредоточиться на достижении своей цели, а также подумать об оптимизации кода.
В таких ситуациях, в которые входит ваша проблема, класс пришел мне на помощь: ChainMapper
Теперь, как работает ChainMapper? следующие несколько пунктов, которые следует учитывать
-> Первый картограф будет считывать файл с HDFS, разбивать каждую строку в соответствии с разделителем и хранить токены в контексте.
-> Второй преобразователь получит выход из первого картографа и здесь вы можете сделать все виды операций, связанных строк, как вы бизнес требует, такие как шифрование текста или изменения в верхний регистр или нижний регистр и т.д.
-> Управляемая строка, которая является результатом второго преобразователя, должна быть снова сохранена в контексте
-> Теперь, если вам нужен редуктор для выполнения задачи агрегации, такой как wordcount, для этого.
У меня есть код, который может быть неэффективным (или некоторые из них могут чувствовать себя ужасно), но он служит вашей цели, как вы могли бы играть с mapreduce.
SplitMapper.java
public class SplitMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
@Override
public void map(Object key,Text value,Context context)
throws IOException,InterruptedException{
StringTokenizer xs=new StringTokenizer(value.toString());
IntWritable dummyValue=new IntWritable(1);
while(xs.hasMoreElements()){
String content=(String)xs.nextElement();
context.write(new Text(content),dummyValue);
}
}
}
LowerCaseMapper.Java
public class LowerCaseMapper extends Mapper<Text,IntWritable,Text,IntWritable>{
@Override
public void map(Text key,IntWritable value,Context context)
throws IOException,InterruptedException{
String val=key.toString().toLowerCase();
Text newKey=new Text(val);
Context.write(newKey,value);
}
}
Поскольку я выступаю в WordCount вот так я требую редуктора
ChainMapReducer.java
public class ChainMapReducer extends Reducer<Text,IntWritable,Text,IntWritable>{
@Override
public void reduce(Text key,Iterable<IntWritable> value,Context context)
throws IOException,InterruptedException{
int sum=0;
for(IntWritable v:value){
sum+=value.get();
}
context.write(key,new IntWritables(sum));
}
}
Чтобы иметь возможность реализовать концепцию chainmapper успешно, вы должны обратить внимание на все детали класса водителя
DriverClass.java
public class DriverClass extends Configured implements Tool{
static Configuration cf;
public int run(String args[]) throws IOException,InterruptedException,ClassNotFoundException{
cf=new Configuration();
Job j=Job.getInstance(cf);
//configuration for the first mapper
Configuration.splitMapConfig=new Configuration(false);
ChainMapper.addMapper(j,SplitMapper.class,Object.class,Text.class,Text.class,IntWritable.class,splitMapConfig);
//configuration for the second mapper
Configuration.lowerCaseConfig=new Configuration(false);
ChainMapper.addMapper(j,LowerCaseMapper.class,Text.class,IntWritable.class,Text.class,IntWritable.class,lowerCaseConfig);
j.setJarByClass(DriverClass.class);
j.setCombinerClass(ChainMapReducer.class);
j.setOutputKeyClass(Text.class);
j.setOutputValueClass(IntWritable.class);
Path outputPath=new Path(args[1]);
FileInputFormat.addInputPath(j,new Path(args[0]));
FileOutputFormat.setOutputPath(j,outputPath);
outputPath.getFileSystem(cf).delete(outputPath,true);
}
public static void main(String args[]) throws Exception{
int res=ToolRunner.run(cf,new DriverClass(),args);
System.exit(1);
}
}
Класс драйвера довольно много понятно, только нужно соблюдать подпись ChainMapper.add(<job-object>,<Map-ClassName>,<Input arguments types>,<configuration-for-the-concerned-mapper>)
Я надеюсь, что решение служит вашей цели, пожалуйста, дайте мне знать в случае возникновения каких-либо проблем, которые могут возникнуть при попытке реализовать.
Thankyou!
Вы попробовали что-нибудь? –
Я нашел несколько примеров, которые показывают, как агрегировать значения по ключам. Например, подсчитайте количество слов в тексте ввода. Мне интересно, есть ли возможность преобразования входных строк вместо вычисления совокупных значений с помощью процедур mapreduce. Это обычная практика, или это не лучшее решение делать такие вещи с уменьшением карты? Я не прошу сделать эту работу для меня, но мне нужен простой пример и подтверждение того, что я в правильном направлении –