5

列挙があるとします:

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 でネットワーク経由で列挙型を送信できなかったということですか、それとも解決策がありますか?

4

3 に答える 3

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

    }

}
于 2012-10-09T13:36:44.203 に答える
1

WritableUtilsには、これを簡単にする便利なメソッドがあります。

WritableUtils.writeEnum(dataOutput,enumData);
enumData = WritableUtils.readEnum(dataInput,MyEnum.class);
于 2014-04-23T16:12:11.803 に答える
0

Hadoopについては何も知りませんが、インターフェースのドキュメントに基づいて、おそらく次のようにすることができます。

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);
    }
}
于 2012-10-09T11:40:10.607 に答える