2012-10-09 14 views
5

के लिखने योग्य इंटरफेस को लागू मूल्य मैं एक गणना है मान लीजिए।Enum Hadoop

बराबर काम नहीं करेंगे, क्योंकि यह गणना के आंतरिक चर पर विचार नहीं करेगा, साथ ही सभी enum उदाहरण संकलन समय पर तय किए गए हैं और कहीं और नहीं बनाया जा सका।

क्या इसका मतलब है कि मैं हैडोप में तार पर enums नहीं भेज सकता या कोई समाधान है?

उत्तर

0

मैं Hadoop बारे में कुछ पता नहीं है, लेकिन पर अंतरफलक के the documentation आधारित है, तो आप ऐसा शायद कर सकता है: Hadoop में enums के लिए

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); 
    } 
} 
+0

जबकि स्थैतिक विधि मनमाने ढंग से फ़ाइलों को कस्टम लिखने के लिए एक अच्छा समाधान है, तो आपको इंटरफेस विधि भरनी होगी, क्योंकि उन्हें आंतरिक रूप से कहा जाता है। जावा एपीआई में बाहरी उपयोग योग्य लेखन योग्य कार्य। –

4

मेरे सामान्य और पसंदीदा समाधान के माध्यम से enums serializing है उनके सामान्य मूल्य।

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_3 साथ ENUM_2 का आदान-प्रदान ऑर्डिनल्स, बदल सकते हैं और एक पहले से धारावाहिक फ़ाइल पढ़ सकते हैं, यह अन्य गलत enum वापस आ जाएगी।

तो अगर आप enum वर्ग पहले से पता है, तुम अपने 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(); 

    } 

} 
+1

इस के लिए एक जोड़ा - यदि आप कुंजी में enum का उपयोग कर रहे हैं, ** ** अपनी कुंजी की हैशकोड विधि के हिस्से के रूप में enum.hashCode() का उपयोग न करें - enum के लिए हैशकोड का कार्यान्वयन डिफ़ॉल्ट मूल कार्यान्वयन है जो एनम प्रकार की स्मृति में पता कम से कम है (जो जेवीएम निर्भर है और जब आप एक ही कुंजी विभिन्न मैपर्स से आउटपुट होते हैं तो वे आपको समस्याएं देंगे - वे संभावित रूप से अलग-अलग reducers के लिए हैश) –

+0

बिल्कुल, यही वह जगह है जहां आप 'लिखने योग्य' प्रकार का उपयोग करना और enhcode के लागू/नाम के आधार पर हैशकोड और बराबर लागू करना चाहते हैं। –

+0

तो, सवाल पर वापस आना - enum के लिए करना संभव नहीं है। केवल सहायक कक्षाओं के माध्यम से। –

1

WritableUtils सुविधा तरीकों कि इस आसान बनाने के है।

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