hadoop实现可写的通用列表

时间:2012-07-03 07:53:03

标签: hadoop

我正在建立一个地图减少作业管道(一个MR作业的输出作为输入提供给另一个)。传递的值相当复杂,因为存在不同类型的列表和具有值作为列表的哈希映射。 Hadoop api似乎没有ListWritable。我试图写一个通用的,但似乎我无法在我的readFields实现中实例化泛型类型,除非我传入类类型本身:

public class ListWritable<T extends Writable> implements Writable {
    private List<T> list;
    private Class<T> clazz;

    public ListWritable(Class<T> clazz) {
       this.clazz = clazz;
       list = new ArrayList<T>();
    }

    @Override
    public void write(DataOutput out) throws IOException {
        out.writeInt(list.size());
        for (T element : list) {
            element.write(out);
        }
     }

     @Override
     public void readFields(DataInput in) throws IOException{
     int count = in.readInt();
     this.list = new ArrayList<T>();
     for (int i = 0; i < count; i++) {
        try {
            T obj = clazz.newInstance();
            obj.readFields(in);
            list.add(obj);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
      }
    }
}

但是hadoop要求所有可写函数都有一个无参数构造函数来读取值。 有没有人试过这样做并解决了这个问题? TIA。

2 个答案:

答案 0 :(得分:2)

我有一个像这样的大量可写函数库,除了我总是将类型声明为自限泛型类型的抽象类,当我使用它时,我声明了一个简单的子类,所有类型都具体化。 Hadoop是如此令人难以置信的反思,你几乎总是更好地不在实际工作中使用泛型;但是,泛型作为作业I / O类型的超类型非常有用。

E.g。

public abstract class AbstractListWritable< T extends Writable & Cloneable, U extends AbstractListWritable< T, U > >
implements Writable {
    T tCursor;
    List< T > ltBacking;
    protected AbstractListWritable( T tCursor ) {
        this.tCursor = tCursor.clone();
        this.ltBacking = new ArrayList< T >();
    }
    ...
    @Override
    public void readFields(DataInput in) throws IOException {
        int count = in.readInt();
        this.ltBacking.clear();
        for (int i = 0; i < count; i++) {
            tCursor.readFields(in);
            list.add(tCursor.clone());
        }
    }
}

public class TextListWritable extends AbstractListWritable< Text, TextListWritable > {
    public TextListWritable() {
        super( new Text() );
    }
}

Thomas的答案将允许异构列表,但由于泛型类型会阻止您创建一个,而I / O几乎总是Hadoop的瓶颈,我不建议使用该策略

答案 1 :(得分:0)

你必须在每条记录中写出真正详细的类名,所以我建议你使用强类型。

但是,您的代码必须更改为:

@Override
public void write(DataOutput out) throws IOException {
    out.writeUTF(clazz.getName());
    out.writeInt(list.size());
    for (T element : list) {
        element.write(out);
    }
 }

 @Override
 public void readFields(DataInput in) throws IOException{
 clazz = Class.forName(in.readUTF());
 int count = in.readInt();
 this.list = new ArrayList<T>();
 for (int i = 0; i < count; i++) {
    try {
        T obj = clazz.newInstance();
        obj.readFields(in);
        list.add(obj);
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
  }
}

然后你也可以提供一个无参数的构造函数。但它将classname作为UTF-8字符串作为每条记录的开销。