将不同的参数传递给每个映射器
Passing different parameters to each mapper
我有一份工作使用多个映射器和一个缩减器。映射器几乎相同,只是它们用于生成结果的 String
的值不同。
目前我有几个 classes,一个对应我提到的 String
的每个值 — 感觉应该有更好的方法,不需要那么多代码重复。有没有办法将这些 String
值作为参数传递给映射器?
我的工作是这样的:
Input File A ----> Mapper A using
String "Foo" ----+
|---> Reducer
Mapper B using ----+
Input File B ----> String "Bar"
我想把它变成这样:
Input File A ----> GenericMapper parameterized
with String "Foo" ----+
|---> Reducer
GenericMapper parameterized ----+
Input File B ----> with String "Bar"
编辑: 这是我目前拥有的两个简化映射器 class。他们准确地代表了我的实际情况。
class MapperA extends Mapper<Text, Text, Text, Text> {
public void map(Text key, Text value, Context context) {
context.write(key, new Text(value.toString() + "Foo"));
}
}
class MapperB extends Mapper<Text, Text, Text, Text> {
public void map(Text key, Text value, Context context) {
context.write(key, new Text(value.toString() + "Bar"));
}
}
编辑:每个映射器应该使用什么字符串只取决于数据来自哪个文件。除了通过文件名,无法区分这些文件。
也许您会在映射器中使用 if 语句在字符串之间进行选择。什么取决于一个字符串或另一个字符串的使用?
或者使用抽象映射器class。
也许是这样的?
abstract class AbstractMapper extends Mapper<Text, Text, Text, Text> {
protected String text;
public void map(Text key, Text value, Context context) {
context.write(key, new Text(value.toString() + text));
}
}
class MapperImpl1 extends AbstractMapper{
@Override
public void map(Text key, Text value, Context context) {
text = "foo";
super.map();
}
}
class MapperImpl2 extends AbstractMapper{
@Override
public void map(Text key, Text value, Context context) {
text = "bar";
super.map();
}
}
假设您使用文件输入格式,您可以像这样在映射器中获取当前输入文件名:
if (context.getInputSplit() instanceof FileSplit) {
FileSplit fileSplit = (FileSplit) context.getInputSplit();
Path inputPath = fileSplit.getPath();
String fileId = ... //parse inputPath into a file id
...
}
您可以根据需要解析 inputPath,例如仅使用文件名或分区 ID 等来生成标识输入文件的唯一 ID。
例如:
/some/path/A -> A
/some/path/B -> B
在驱动程序中为每个可能的文件配置属性 "id":
conf.set("my.property.A", "foo");
conf.set("my.property.B", "bar");
在映射器计算文件中 "id" 如上所述并获取值:
conf.get("my.property." + fileId);
我有一份工作使用多个映射器和一个缩减器。映射器几乎相同,只是它们用于生成结果的 String
的值不同。
目前我有几个 classes,一个对应我提到的 String
的每个值 — 感觉应该有更好的方法,不需要那么多代码重复。有没有办法将这些 String
值作为参数传递给映射器?
我的工作是这样的:
Input File A ----> Mapper A using
String "Foo" ----+
|---> Reducer
Mapper B using ----+
Input File B ----> String "Bar"
我想把它变成这样:
Input File A ----> GenericMapper parameterized
with String "Foo" ----+
|---> Reducer
GenericMapper parameterized ----+
Input File B ----> with String "Bar"
编辑: 这是我目前拥有的两个简化映射器 class。他们准确地代表了我的实际情况。
class MapperA extends Mapper<Text, Text, Text, Text> {
public void map(Text key, Text value, Context context) {
context.write(key, new Text(value.toString() + "Foo"));
}
}
class MapperB extends Mapper<Text, Text, Text, Text> {
public void map(Text key, Text value, Context context) {
context.write(key, new Text(value.toString() + "Bar"));
}
}
编辑:每个映射器应该使用什么字符串只取决于数据来自哪个文件。除了通过文件名,无法区分这些文件。
也许您会在映射器中使用 if 语句在字符串之间进行选择。什么取决于一个字符串或另一个字符串的使用?
或者使用抽象映射器class。
也许是这样的?
abstract class AbstractMapper extends Mapper<Text, Text, Text, Text> {
protected String text;
public void map(Text key, Text value, Context context) {
context.write(key, new Text(value.toString() + text));
}
}
class MapperImpl1 extends AbstractMapper{
@Override
public void map(Text key, Text value, Context context) {
text = "foo";
super.map();
}
}
class MapperImpl2 extends AbstractMapper{
@Override
public void map(Text key, Text value, Context context) {
text = "bar";
super.map();
}
}
假设您使用文件输入格式,您可以像这样在映射器中获取当前输入文件名:
if (context.getInputSplit() instanceof FileSplit) {
FileSplit fileSplit = (FileSplit) context.getInputSplit();
Path inputPath = fileSplit.getPath();
String fileId = ... //parse inputPath into a file id
...
}
您可以根据需要解析 inputPath,例如仅使用文件名或分区 ID 等来生成标识输入文件的唯一 ID。 例如:
/some/path/A -> A
/some/path/B -> B
在驱动程序中为每个可能的文件配置属性 "id":
conf.set("my.property.A", "foo");
conf.set("my.property.B", "bar");
在映射器计算文件中 "id" 如上所述并获取值:
conf.get("my.property." + fileId);