我正在建立一个地图减少作业管道(一个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.
最佳答案 我有一个像这样的大量可写函数库,除了我总是将类型声明为自限泛型类型的抽象类,当我使用它时,我声明了一个简单的子类,所有类型都具体化. Hadoop是如此令人难以置信的反思,你几乎总是更好地不在实际工作中使用泛型;但是,泛型作为作业I / O类型的超类型非常有用.
例如.
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() );
}
}
托马斯的答案将允许异构列表,除了因为泛型类型会阻止你创建一个,而I / O几乎总是Hadoop的瓶颈,我不推荐这种策略.