2013-06-17 5 views
0

Я видел странное поведение при использовании Avro в MapReduce Job. Действительно, Iterable используется очень странно: iterator.next не указывает на объект, а на то, что меняет его значение при каждом вызове функции «next» !!Странное поведение Iterable в AVRO (внутри MapReduce)

Пример:

public static class MyAvroReducer extends AvroReducer<Long, MyAvroType, 
Pair<Long, MyAvroType>> { 


    @Override 
    public void reduce(Long user, Iterable<MyAvroType> listAvroType, 
      AvroCollector<Pair<Long,MyAvroType>> collector, 
      Reporter reporter) 
    throws IOException { 
     // basically here I am expecting a list of two MyAvroType object 
     // The first one who has a field "type" equals to "foo" and the second 
     // who has a filed "type" equals to "bar" 

     MyAvroType foo; 
     MyAvroType bar; 

     for (MyAvroType obj : listAvroType){ 
      if (obj.getType().equals("foo") {foo = obj;} 
      else if (obj.getType().equals("bar") {bar = obj;} 

     } 
     system.out.println("FOO: " + foo.getType()); 
     system.out.println("FOO: " + bar.getType()); 

} 

Стандартный вывод говорит:

FOO: бар

BAR: бар

Как было закодировал Iterable здесь? и почему ?? Или, может, я что-то не так?

ответ

1

Я нашел ваш вопрос, потому что у меня была та же проблема. Тесты, которые я запускал, показывают, что Iterable возвращает только один экземпляр для всех итераций. Iterable должен заменять содержимое одного и того же объекта каждый раз, когда он считывает новый объект AVRO. Я закончил список из тысячи последних возвращенных объектов. Я обнаружил, что, как только я назвал iterator.next(), объект, который у меня был из предыдущей итерации, внезапно превратится в новый объект.

Я могу понять, почему они делают это таким образом, поскольку Iterable используется для включения неограниченного количества объектов в процессе обработки, то есть больше, чем может быть помещено в память за один раз. Таким образом, они не ожидают, что кто-либо будет удерживать объект после вызова iterator.next().

Если вам нужно обратиться к любым предыдущим объектам, возвращенным из итерируемого, вам нужно будет скопировать объект в новый экземпляр перед тем, как перейти к следующему объекту в Iterable.

Я использовал Cloner из инструмента клонирования Google 1.8.8 для решения проблемы. Мои объекты около пяти или шести уровней глубины гнездования, но, похоже, это сработало.

Google cloning-1.8.5

Другой альтернативой было бы реализовать свой собственный метод копирования на каждом объекте.

Спасибо, Вики

+0

Спасибо за ваш ответ, я использовал клонирование тоже решить problème. Кстати, я могу понять оптимизацию, но это не то, что разработчик ожидает от поведения итератора ... – stefff