복붙노트

[HADOOP] Hadoop의 Writable 인터페이스를 구현하는 Enum 값

HADOOP

Hadoop의 Writable 인터페이스를 구현하는 Enum 값

열거 형이 있다고 가정합니다.

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는 열거 형의 내부 변수를 고려하지 않기 때문에 작동하지 않으며, 모든 enum 인스턴스는 컴파일 타임에 고정되어 다른 곳에 만들 수 없습니다.

하둡의 전선을 통해 enum을 보낼 수 없다는 뜻입니까 아니면 해결책이 있습니까?

해결법

  1. ==============================

    1.Hadoop의 열거 형에 대한 내 정상적이고 바람직한 솔루션은 서수 값을 통해 열거 형을 직렬화하는 것입니다.

    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_2를 교환하고 이전에 직렬화 된 파일을 읽으면 다른 잘못된 enum을 반환합니다.

    따라서 열거 형 클래스를 미리 아는 경우 열거 형 이름을 작성하고 다음과 같이 사용할 수 있습니다.

     enumInstance = EnumName.valueOf(in.readUTF());
    

    이렇게하면 약간 더 많은 공간이 사용되지만 enum 이름을 변경하면 더 많은 공간이 절약됩니다.

    전체 예제는 다음과 같습니다.

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

    2.WritableUtils에는 이것을보다 쉽게 ​​해주는 편리한 메소드가 있습니다.

    WritableUtils에는 이것을보다 쉽게 ​​해주는 편리한 메소드가 있습니다.

    WritableUtils.writeEnum(dataOutput,enumData);
    enumData = WritableUtils.readEnum(dataInput,MyEnum.class);
    
  3. ==============================

    3.저는 Hadoop에 대해 아무것도 모릅니다 만, 인터페이스의 문서화를 기반으로하면 아마 그렇게 할 수 있습니다.

    저는 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);
        }
    }
    
  4. from https://stackoverflow.com/questions/12799014/enum-value-implementing-writable-interface-of-hadoop by cc-by-sa and MIT license