В Hadoop, если вы хотите сохранить значения из каждой пары ключ-значение в массиве, почему все добавляемые элементы одинаковы? - PullRequest
1 голос
/ 29 декабря 2011

Я пытаюсь сохранить значения из пар ключ-значение, которые получает функция Map, и использовать их в дальнейшем.С учетом следующего ввода:

Hello hadoop goodbye hadoop
Hello world goodbye world
Hello thinker goodbye thinker

и следующий код:

Примечание - карта представляет собой простой пример WordCount

public class Inception extends Configured implements Tool{

public Path workingPath;

 public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

     // initialising the arrays that contain the values and the keys
    public ArrayList<LongWritable> keyBuff = new ArrayList<LongWritable>();
    public ArrayList<Text> valueBuff = new ArrayList<Text>();


    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String line = value.toString();
        StringTokenizer tokenizer = new StringTokenizer(line);

        while (tokenizer.hasMoreTokens()) {
            word.set(tokenizer.nextToken());
            context.write(word, one);
            System.out.println(word + " / " + one);
        }
    }   

    public void innerMap(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

            // adding the value to the bufferr
        valueBuff.add(value);
        System.out.println("ArrayList addValue -> " + value);
        for (Text v : valueBuff){
            System.out.println("ArrayList containedValue -> " + value);
        }

        keyBuff.add(key);

        }   

    public void run(Context context) throws IOException, InterruptedException {
        setup(context);

        // going over the key-value pairs and storing them into the arrays
        while(context.nextKeyValue()){
            innerMap(context.getCurrentKey(), context.getCurrentValue(), context);
        }


        Iterator itrv = valueBuff.iterator();
        Iterator itrk = keyBuff.iterator();
        while(itrv.hasNext()){
            LongWritable nextk = (LongWritable) itrk.next();
            Text nextv = (Text) itrv.next();
            System.out.println("Value iterator -> " + nextv);
            System.out.println("Key iterator -> " + nextk);

            // iterating over the values and running the map on them.

            map(nextk, nextv, context);
        }

        cleanup(context);
    }
 }

 public int run(String[] args) throws Exception { ... }

 public static void main (..) { ... }

Okтеперь выводится лог:

stdout logs

ArrayList addValue -> Hello hadoop goodbye hadoop
ArrayList containedValue -> Hello hadoop goodbye hadoop
ArrayList addValue -> Hello world goodbye world
ArrayList containedValue -> Hello world goodbye world
ArrayList containedValue -> Hello world goodbye world
ArrayList addValue -> Hello thinker goodbye thinker
ArrayList containedValue -> Hello thinker goodbye thinker
ArrayList containedValue -> Hello thinker goodbye thinker
ArrayList containedValue -> Hello thinker goodbye thinker
Value iterator -> Hello thinker goodbye thinker
Key iterator -> 84
Hello / 1
thinker / 1
goodbye / 1
thinker / 1
Value iterator -> Hello thinker goodbye thinker
Key iterator -> 84
Hello / 1
thinker / 1
goodbye / 1
thinker / 1
Value iterator -> Hello thinker goodbye thinker
Key iterator -> 84
Hello / 1
thinker / 1
goodbye / 1
thinker / 1

Итак, вы можете заметить, что каждый раз, когда я добавляю новое значение в значение ArrayList, всезначения в списке перезаписываются.Кто-нибудь знает, почему это происходит, и почему значения не добавляются в массив должным образом?

1 Ответ

2 голосов
/ 30 декабря 2011

TextInputFormat использует LineRecordReader . Когда вызывается Context # nextKeyValue, вызывается LineRecordReader # nextKeyValue.

В LineRecordReader одни и те же объекты ключа и значения используются при каждом вызове метода nextKeyValue, изменяется только их содержимое. Копия объекта должна быть сделана в коде пользователя, если должны храниться данные ключа и значения.

Это имеет смысл для оптимизации, если для каждой записи создается новый объект ключа и значения, тогда система будет легко выполнять OOM.

...