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();
}
}