假设我有一个枚举:
public enum SomeEnumType implements Writable {
A(0), B(1);
private int value;
private SomeEnumType(int value) {
this.value = value;
}
@Override
public void write(final DataOutput dataOutput) throws IOException {
dataOutput.writeInt(this.value);
}
@Override
public void readFields(final DataInput dataInput) throws IOException {
this.value = dataInput.readInt();
}
}
我想将其实例作为其他类实例的一部分传递。
equals不起作用,因为它不会考虑枚举的内部变量,加上所有枚举实例在编译时都是固定的,不能在其他地方创建。
这是否意味着我无法在Hadoop中通过网络发送枚举或有解决方案?
答案 0 :(得分:4)
我在Hadoop中对枚举的正常和首选解决方案是通过序数值序列化枚举。
public class EnumWritable implements Writable {
static enum EnumName {
ENUM_1, ENUM_2, ENUM_3
}
private int enumOrdinal;
// never forget your default constructor in Hadoop Writables
public EnumWritable() {
}
public EnumWritable(Enum<?> arbitraryEnum) {
this.enumOrdinal = arbitraryEnum.ordinal();
}
public int getEnumOrdinal() {
return enumOrdinal;
}
@Override
public void readFields(DataInput in) throws IOException {
enumOrdinal = in.readInt();
}
@Override
public void write(DataOutput out) throws IOException {
out.writeInt(enumOrdinal);
}
public static void main(String[] args) {
// use it like this:
EnumWritable enumWritable = new EnumWritable(EnumName.ENUM_1);
// let Hadoop do the write and read stuff
EnumName yourDeserializedEnum = EnumName.values()[enumWritable.getEnumOrdinal()];
}
}
显然它有缺点:普通可以改变,所以如果你用ENUM_2
交换ENUM_3
并读取以前的序列化文件,这将返回另一个错误的枚举。
因此,如果您事先知道枚举类,则可以编写枚举的名称并使用它:
enumInstance = EnumName.valueOf(in.readUTF());
这将使用稍多的空间,但更改为枚举名称更加省钱。
完整示例如下所示:
public class EnumWritable implements Writable {
static enum EnumName {
ENUM_1, ENUM_2, ENUM_3
}
private EnumName enumInstance;
// never forget your default constructor in Hadoop Writables
public EnumWritable() {
}
public EnumWritable(EnumName e) {
this.enumInstance = e;
}
public EnumName getEnum() {
return enumInstance;
}
@Override
public void write(DataOutput out) throws IOException {
out.writeUTF(enumInstance.name());
}
@Override
public void readFields(DataInput in) throws IOException {
enumInstance = EnumName.valueOf(in.readUTF());
}
public static void main(String[] args) {
// use it like this:
EnumWritable enumWritable = new EnumWritable(EnumName.ENUM_1);
// let Hadoop do the write and read stuff
EnumName yourDeserializedEnum = enumWritable.getEnum();
}
}
答案 1 :(得分:1)
WritableUtils提供了方便的方法,可以让您更轻松。
WritableUtils.writeEnum(dataOutput,enumData);
enumData = WritableUtils.readEnum(dataInput,MyEnum.class);
答案 2 :(得分:0)
我对Hadoop一无所知,但基于界面的the documentation,您可能会这样做:
public void readFields(DataInput in) throws IOException {
// do nothing
}
public static SomeEnumType read(DataInput in) throws IOException {
int value = in.readInt();
if (value == 0) {
return SomeEnumType.A;
}
else if (value == 1) {
return SomeEnumType.B;
}
else {
throw new IOException("Invalid value " + value);
}
}