2010-03-19 8 views
13

मुझे विभिन्न आदिम प्रकारों पर एल्गोरिदम करने की आवश्यकता है; एल्गोरिदम अनिवार्य रूप से वही है जो चर के प्रकार के अपवाद के साथ समान है। तो उदाहरण के लिए,प्राचीन प्रकार के साथ काम करते समय पुनरावृत्ति से कैसे बचें?

/** 
* Determine if <code>value</code> is the bitwise OR of elements of <code>validValues</code> array. 
* For instance, our valid choices are 0001, 0010, and 1000. 
* We are given a value of 1001. This is valid because it can be made from 
* ORing together 0001 and 1000. 
* On the other hand, if we are given a value of 1111, this is invalid because 
* you cannot turn on the second bit from left by ORing together those 3 
* valid values. 
*/ 
public static boolean isValid(long value, long[] validValues) { 
    for (long validOption : validValues) { 
     value &= ~validOption; 
    } 
    return value == 0; 
} 

public static boolean isValid(int value, int[] validValues) { 
    for (int validOption : validValues) { 
     value &= ~validOption; 
    } 
    return value == 0; 
} 

मैं इस पुनरावृत्ति से कैसे बच सकता हूं? मुझे पता है कि आदिम सरणी उत्पन्न करने का कोई तरीका नहीं है, इसलिए मेरे हाथ बंधे हुए लगते हैं। मेरे पास आदिम सरणी के उदाहरण हैं और नंबर ऑब्जेक्ट्स के बॉक्स किए गए सरणी नहीं हैं, इसलिए मैं उस मार्ग को भी नहीं जाना चाहता हूं।

मुझे पता है कि एरे, ऑटोबॉक्सिंग इत्यादि के संबंध में प्राइमेटिव के बारे में बहुत सारे प्रश्न हैं, लेकिन मैंने इसे इस तरह से तैयार नहीं देखा है, और मैंने बातचीत करने के तरीके पर निर्णायक उत्तर नहीं देखा है इन सरणी के साथ।

मैं मैं की तरह कुछ कर सकता है लगता है:

public static<E extends Number> boolean isValid(E value, List<E> numbers) { 
    long theValue = value.longValue(); 
    for (Number validOption : numbers) { 
     theValue &= ~validOption.longValue(); 
    } 
    return theValue == 0; 
} 

और फिर

public static boolean isValid(long value, long[] validValues) { 
    return isValid(value, Arrays.asList(ArrayUtils.toObject(validValues))); 
} 

public static boolean isValid(int value, int[] validValues) { 
    return isValid(value, Arrays.asList(ArrayUtils.toObject(validValues))); 
} 

कि हालांकि वास्तव में काफी बेहतर है? इस तरह मूल कार्यान्वयन की तुलना में बहुत अधिक वस्तुएं पैदा होंगी, हालांकि यह स्रोत कोड को डीआरवाई करता है। इस मामले में किसी भी विचार की सराहना की जाएगी।

+0

शानदार सवाल। यद्यपि मैं जेनेरिक के साथ ऐसा करने का कोई तरीका नहीं देख सकता, पूरी तरह से असंबंधित नोट पर, 1.5 सिंटैक्स में पुनरावृत्ति को प्रबंधित करने के तरीके के कारण, मुझे लगता है कि आप प्रत्येक नंबर के लिए ऑटोबॉक्सिंग कर रहे हैं। मुझे लगता है कि पुराने स्टाइल सरणी गिनती करने के लिए यह तेज़ होगा। –

+1

@ I82Much: यहां मेरा जवाब और टॉम हौटिन द्वारा टिप्पणी देखें: http://stackoverflow.com/questions/2337170/managing-highly-repetitive-code-and-documentation-in-java मूल रूप से कोई "आसान" तरीका नहीं है। आपको या तो पुनरावृत्ति की पागल राशि से निपटना होगा या कस्टम प्री-प्रोसेसर या सोर्स-कोड इंस्ट्रूमेंटेशन या कुछ टेम्पलेटिंग सिस्टम का उपयोग करना होगा। तथ्य यह है कि यहां तक ​​कि सूर्य ऐसी तकनीक का उपयोग कर रहा है साबित करता है कि इसका उपयोग है। असल में यह भी है कि अद्भुत ट्रोव प्राइमेटिव संग्रह यह कैसे कर रहा है। Polygenelubricants के सवाल और मेरे +5 ऊपर उल्लिखित/स्वीकार्य उत्तर देखें। – SyntaxT3rr0r

उत्तर

6

मैंने पहले (Managing highly repetitive code and documentation in Java) एक समान प्रश्न पूछा, और कहा कि java.util.Arrays के लिए स्रोत कोड आदिम सरणी प्रकार से निपटने के लिए अत्यधिक अपने एल्गोरिदम में दोहराव है।

सात आदिम प्रकार से प्रत्येक के लिए कोड काफी हद तक समान होता है:

वास्तव में, स्रोत कोड इस टिप्पणी में शामिल है। C'est ला vie।

जो उत्तर मैंने स्वीकार किया है वह कोड जनरेटर के उपयोग का सुझाव देता है जो आपको इसके बजाय कोड टेम्पलेट्स के साथ काम करने देता है। एक टिप्पणी भी है कि सूर्य/ओरेकल आंतरिक रूप से एक टेम्पलेटिंग सिस्टम का भी उपयोग करता है।

आप पुनरावृत्ति को कम करने के लिए प्रतिबिंब का भी उपयोग कर सकते हैं, लेकिन यह धीमा होने की संभावना है, और शायद प्रयास के लायक नहीं है। आप इसके प्रदर्शन का परीक्षण करना चाहते हैं, तो इस स्निपेट तकनीक को दर्शाता है:

import java.lang.reflect.Array; 

static long maskFor(Class<?> c) { 
    return (
     c.equals(int.class) ? 1L << Integer.SIZE : 
     c.equals(short.class) ? 1L << Short.SIZE : 
     c.equals(byte.class) ? 1L << Byte.SIZE : 
     0 
    ) - 1; 
} 
public static void reflectPrimitiveNumericArray(Object arr) throws Exception { 
    int length = Array.getLength(arr); 
    Class<?> componentType = arr.getClass().getComponentType(); 
    long mask = maskFor(componentType); 
    System.out.format("%s[%d] = { ", componentType, length); 
    for (int i = 0; i < length; i++) { 
     long el = Array.getLong(arr, i) & mask; 
     System.out.print(Long.toBinaryString(el) + " "); 
    } 
    System.out.println("}"); 
} 

आप arr के लिए एक int[], साथ ही अन्य आदिम सरणी प्रकार पारित कर सकते हैं। साइन एक्सटेंशन को संबोधित करने के लिए बिट-मास्किंग के साथ, सब कुछ long में डाला गया है।

reflectPrimitiveNumericArray(new byte[] { (byte) 0xF0 }); 
// byte[1] = { 11110000 } 
reflectPrimitiveNumericArray(new int[] { 0xF0F0F0F0 }); 
// int[1] = { 11110000111100001111000011110000 } 
reflectPrimitiveNumericArray(new long[] { 0xF0F0F0F0F0F0F0F0L }); 
// long[1] = { 1111000011110000111100001111000011110000111100001111000011110000 } 
+0

-1 - मेरा लेना यह है कि जब तक डुप्लिकेट कोड हजारों लाइनों तक नहीं होता है, तब तक मिश्रण में कोड जनरेशन शुरू करने से कोड को बनाए रखने के लिए हार्डर्ड बनने की संभावना है ... विशेष रूप से उन लोगों के लिए जो कोड कोड तकनीक से पहले से परिचित नहीं हैं। –

+1

मैं सिर्फ अपने प्रश्न से जो कुछ सीखा वह साझा कर रहा हूं। ओपी पर निर्भर है कि इस ज्ञान के साथ क्या करना है। – polygenelubricants

+1

@ स्टीफन सी: +1 ... वास्तव में उसे कम करने की कोई ज़रूरत नहीं है (बीटीडब्ल्यू मैंने स्वीकार किए गए उत्तर को लिखा है)। आपको स्रोत कोड जनरेशन पसंद नहीं हो सकता है, हो सकता है कि आप यह नहीं चाहें कि अन्य लोग इसे कर रहे हैं ... लेकिन वह * आईएस * कैसे लोग उच्च प्रदर्शन वाले संग्रह लिखते हैं जो प्राइमेटिव के साथ काम करते हैं। एक ट्रोव देखो। उनके TLongLongHashMap/TIntIntHashMap आदि डिफ़ॉल्ट जावा संग्रह स्मृति और प्रदर्शन के अनुसार पूरी तरह से नष्ट कर देते हैं। और वे यह कैसे करते हैं? स्रोत कोड जनरेशन/टेम्पलेट्स/प्री-प्रोसेसर इत्यादि। ऐसे कई मामले हैं जहां ये तकनीक उपयोगी हैं और जहां वे वास्तविक लाभ प्रदान करते हैं। – SyntaxT3rr0r

2

मुझे लगता है कि आप भाग्य से बाहर हैं मुझे डर है - प्राचीन प्रकार से दूर जाने के बिना।

5

आप java.util.Arrays में देखो, तो आप यह है कि वे एक आदिम प्रकार के लिए अपने सभी एल्गोरिदम (binarySearch, equals, आदि) के विशेषज्ञ करना पड़ा दिखाई देगी।

यदि प्रदर्शन एक मुद्दा है, तो मैं autoboxing पर भरोसा करने की अनुशंसा नहीं करता, लेकिन यदि नहीं (आपके प्रोफाइल के बाद), तो यह एक वैध विकल्प होगा।

1

पिछले जीवन में, हम (बेडौल सरणियों और इस तरह का उपयोग कर, स्मृति में आदेश के लाखों लोगों) कुछ आदिम टाइप संग्रह है कि वित्तीय डेटा के लिए अनुकूलित किया गया था। हमारा समाधान कुछ स्टब फाइलों के साथ ट्रोव की तरह था। 'मूल' स्रोत फ़ाइल कहां होगी ... उदाहरण के लिए हैशसेट_की। कुंजी और मूल्य के लिए कुछ ठूंठ वर्गों के साथ, हम एक HashSetInt, HashSetLong, आदि उत्पन्न करने के लिए चींटी कार्य का उपयोग करने का निधि के मॉडल ...

मैं हमेशा सोचा कि यह था एक 'janky' विधि का पालन, लेकिन यह काम किया । मुझे उत्सुकता है कि किसी ने कभी भी वेग, या संभवतः एफएमपीपी की कोशिश की है, और कुछ हल्के क्लीनर परिणाम हैं? चींटी समाधान के साथ मेरी मुख्य समस्या यह है कि सभी कोड एक साथ बहुत करीब रहते हैं, जबकि बहुत से स्रोत कोड पीढ़ी में आप टेम्पलेट फ़ाइलों को बेहतर तरीके से अलग करने में सक्षम हो सकते हैं।

संबंधित मुद्दे