hadoop实现了一个通用的可写列表

hadoop实现了一个通用的可写列表,hadoop,Hadoop,我正在构建一个工作流程图(将一个MR工作的输出作为输入反馈给另一个MR工作)。传递的值相当复杂,因为有不同类型的列表和以值为列表的哈希映射。Hadoop api似乎没有可写列表。我正在尝试编写泛型类型,但似乎无法在readFields实现中实例化泛型类型,除非传入类类型本身: public class ListWritable<T extends Writable> implements Writable { private List<T> list; p

我正在构建一个工作流程图(将一个MR工作的输出作为输入反馈给另一个MR工作)。传递的值相当复杂,因为有不同类型的列表和以值为列表的哈希映射。Hadoop api似乎没有可写列表。我正在尝试编写泛型类型,但似乎无法在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();
        }
      }
    }
}
公共类ListWritable实现了可写{
私人名单;
私人课堂;
公共列表可写(类clazz){
this.clazz=clazz;
列表=新的ArrayList();
}
@凌驾
public void write(DataOutput out)引发IOException{
out.writeInt(list.size());
对于(T元素:列表){
元素。写出;
}
}
@凌驾
public void readFields(DataInput in)引发IOException{
int count=in.readInt();
this.list=new ArrayList();
for(int i=0;i
但是hadoop要求所有可写文件都有一个无参数构造函数来读回这些值。 有没有人尝试过同样的方法来解决这个问题?
TIA。

您必须在每条记录中写入类名,这非常详细,因此我建议您输入强类型

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

@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();
    }
  }
}
@覆盖
public void write(DataOutput out)引发IOException{
out.writeUTF(clazz.getName());
out.writeInt(list.size());
对于(T元素:列表){
元素。写出;
}
}
@凌驾
public void readFields(DataInput in)引发IOException{
clazz=Class.forName(in.readUTF());
int count=in.readInt();
this.list=new ArrayList();
for(int i=0;i

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

我有一个类似这样的可写库,只是我总是将该类型声明为一个自绑定泛型类型的抽象类,当我使用它时,我声明一个平凡的子类,所有类型都是具体的。Hadoop是如此可怕地基于反射,以至于在实际工作中不使用泛型几乎总是更好;但是,泛型作为作业I/O类型的超类型非常有用

例如

公共抽象类AbstractListWritable>
实现可写{
特库索;
列表ltBacking;
受保护的AbstractListWritable(tCursor){
this.tCursor=tCursor.clone();
this.ltBacking=newarraylist();
}
...
@凌驾
public void readFields(DataInput in)引发IOException{
int count=in.readInt();
this.ltBacking.clear();
for(int i=0;i{
公共TextListWritable(){
超级(新文本());
}
}

Thomas的回答将允许异构列表,但由于泛型类型将阻止您创建一个列表,并且I/O几乎总是Hadoop中的瓶颈,因此我不建议采用这种策略。

谢谢。那么,在您的情况下,您需要实现readFields并在这个抽象基类型的具体实现中编写它吗?事实上,这正是我想要避免的。您已经规定列表的元素类型扩展为可写,因此可以使用原始post中的实现。更新:我现在看到问题了。在这种情况下,您可以在具体类中创建一个“cursor”T实例,并在readFields的基类实现中使用它。T还必须实现Cloneable。谢谢Thomas。让我看看我是否能忍受在每条记录中写入额外的数据位。太好了,我希望我们能假设T总是相同的类型。否则,您必须用列表中的每个元素编写类名,这比上面的要详细得多。
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() );
    }
}