Как исправить неправильное поведение строкового значения, заданного методом настройки mapper в mapreduce? - PullRequest
0 голосов
/ 12 апреля 2019

Я очень новичок в MapReduce и узнал о реализации метода установки. Новое строковое значение, заданное конфигурацией, печатается правильно, но когда я попытался обработать его, начальное значение строки вступает в действие. Я знаю, что строка неизменна, но она должна предоставлять значение, на которое в данный момент указывают другие методы.

public class EMapper extends Mapper<LongWritable, Text, Text, Text> {

    String wordstring = "abcd"; //initialized wordstring with "abcd"


    public void setup(Context context) {
        Configuration config = new Configuration(context.getConfiguration());
        wordstring = config.get("mapper.word"); // As string is immutable,
        // wordstring should now point to
        // value given by mapper.word
        //Here mapper.word="ankit" by 
        //using -D in hadoop command

    }

    String def = wordstring;
    String jkl = String.valueOf(wordstring); //tried to copy current value 
    //but 
    //string jkl prints the initial 
    /value.

    public void map(LongWritable key, Text value, Context context)
    throws InterruptedException, IOException {
        context.write(new Text("wordstring=" + wordstring + "   " + "def=" + 
                def),
            new Text("jkl=" + jkl));
    }
}


public class EDriver extends Configured implements Tool {

    private static Logger logger = LoggerFactory.getLogger(EDriver.class);


    public static void main(String[] args) throws Exception {
        logger.info("Driver started");

        int res = ToolRunner.run(new Configuration(), new EDriver(), args);
        System.exit(res);
    }

    public int run(String[] args) throws Exception {
        if (args.length != 2) {
            System.err.printf("Usage: %s  needsarguments",
                getClass().getSimpleName());
            return -1;
        }
        Configuration conf = getConf();
        Job job = new Job(conf);
        job.setJarByClass(EDriver.class);
        job.setJobName("E Record Reader");

        job.setMapperClass(EMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
        job.setReducerClass(EReducer.class);
        job.setNumReduceTasks(0);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(NullWritable.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        job.setInputFormatClass(ExcelInputFormat.class);

        return job.waitForCompletion(true) ? 0 : 1;
    }

} 

Я ожидал, что результат будет

   wordstring=ankit   def=ankit   jkl=ankit

Фактический вывод

   wordstring=ankit   def=abcd    jkl=abcd

Ответы [ 2 ]

0 голосов
/ 13 апреля 2019

Проблема была решена.На самом деле, я запускал Hadoop в распределенном режиме, когда SETUP, MAPPER, REDUCER и CLEANUP работают на разных JVM.Таким образом, данные не могут быть перенесены из SETUP в MAPPER напрямую.Первый объект wordstring был инициализирован как "abcd" в mapper.Я попытался изменить строку слов в SETUP (был создан другой объект wordstring), который фактически имел место в другой JVM.Итак, когда я попытался скопировать «wordstring» в jkl в

String jkl = String.valueOf (wordstring);

первое значение wordstring (то, которое было создано mapper и инициализировано в)abcd ") копировался в jkl.

Если я запустил Hadoop в автономном режиме, он будет использовать одну JVM, а значение, заданное для wordstring с помощью SETUP, будет скопировано в jkl.

Таким образом, jkl получил копию строки слов, инициализированную в "abcd", а не копию, заданную SETUP.

Я использовал

HashMap map = new HashMap ();

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

0 голосов
/ 12 апреля 2019

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

Ваш setup метод будет вызываться только после выполнения любых команд на уровне класса. Порядок написания кода ничего не меняет. Если бы вы переписали верхнюю часть вашего кода в том порядке, в котором он фактически выполняется, вы бы получили:

public class EMapper extends Mapper<LongWritable, Text, Text, Text> {
    String wordstring = "abcd";
    String jkl = String.valueOf(wordstring);

    public void setup(Context context) {
        Configuration config = new Configuration(context.getConfiguration());
        wordstring = config.get("mapper.word"); //By the time this is called, jkl has already been assigned to "abcd"
    }

Так что не удивительно, что jkl по-прежнему abcd. Вы должны установить jkl в методе setup, например:

public class EMapper extends Mapper<LongWritable, Text, Text, Text> {
    String wordstring;
    String jkl;

    public void setup(Context context) {
        Configuration config = new Configuration(context.getConfiguration());
        wordstring = config.get("mapper.word");
        jkl = wordstring;
        //Here, jkl and wordstring are both different variables pointing to "ankit"
    }

    //Here, jkl and wordstring are null, as setup(Context context) has not yet run

    public void map(LongWritable key, Text value, Context context)
        throws InterruptedException, IOException {
        //Here, jkl and wordstring are both different variables pointing to "ankit"
        context.write(new Text("wordstring=" + wordstring),
            new Text("jkl=" + jkl));
    }

Конечно, на самом деле вам не нужен jkl, вы можете просто использовать wordstring.

...