मानचित्र में सम्मिलन क्रम मायने कैसे रखता है?


24

मैं डेटाबेस से टुपल्स का एक सेट ला रहा हूं, और इसे एक मानचित्र में डाल रहा हूं। डेटाबेस क्वेरी महंगा है।

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

public LinkedHashMap<Key, Value> fetchData()

मेरे पास एक तरीका है processDataजो मानचित्र पर कुछ प्रसंस्करण करना चाहिए - कुछ मूल्यों को संशोधित करना, कुछ नई कुंजी / मान जोड़ना। इसे परिभाषित किया गया है

public void processData(LinkedHashMap<Key, Value> data) {...}

हालांकि, कई लिंटर्स (सोनार आदि) की शिकायत है कि 'लिंक्डहैशप्रेम' ( स्क्वीड S1319 ) के कार्यान्वयन के बजाय 'डेटा' का प्रकार एक इंटरफ़ेस होना चाहिए जैसे कि 'मैप'
तो मूल रूप से यह कह रहा है कि मुझे होना चाहिए

public void processData(Map<Key, Value> data) {...}

लेकिन मैं चाहता हूं कि विधि हस्ताक्षर यह कहने के लिए कि नक्शा आदेश मायने रखता है - यह एल्गोरिथ्म के लिए मायने रखता है processData- ताकि मेरी विधि किसी भी यादृच्छिक नक्शे से पारित न हो।

मैं उपयोग नहीं करना चाहता SortedMap, क्योंकि यह (के javadoc सेjava.util.SortedMap ) " अपनी कुंजियों के प्राकृतिक आदेश के अनुसार , या एक तुलनित्र द्वारा आदेश दिया गया है आमतौर पर क्रमबद्ध मानचित्र निर्माण समय पर प्रदान किया जाता है।"

मेरी कुंजियों में एक प्राकृतिक क्रम नहीं है , और कुछ भी नहीं करने के लिए एक तुलनित्र बनाना क्रिया लगता है।

और मैं अब भी यह चाहूंगा कि putनक़ल कीज़ आदि से बचने के लिए इसका नक़्शा बनाया जाए, अगर ऐसा नहीं किया dataजा सकता है List<Map.Entry<Key, Value>>

तो मैं यह कैसे कहूं कि मेरा तरीका पहले से हल किए गए नक्शे को चाहता है ? अफसोस की बात है कि कोई java.util.LinkedMapइंटरफ़ेस नहीं है, या मैंने इसका इस्तेमाल किया होगा।

जवाबों:


56

इसलिए उपयोग करें LinkedHashMap

हाँ , आपको Mapजब भी संभव हो एक विशिष्ट कार्यान्वयन का उपयोग करना चाहिए , और हाँ , यह है सबसे अच्छा अभ्यास।

उस ने कहा, यह एक अजीब तरह की विशिष्ट स्थिति है जहां Mapवास्तव में लागू होना मायने रखता है। जब आप उपयोग करते हैं तो यह आपके कोड में 99.9% मामलों के लिए सही नहीं होगाMap , और फिर भी आप इस 0.1% स्थिति में हैं। सोनार यह नहीं जान सकता है और इसलिए सोनार आपको बताता है कि विशिष्ट कार्यान्वयन का उपयोग करने से बचें क्योंकि यह ज्यादातर मामलों में सही होगा।

मेरा तर्क है कि यदि आप एक विशिष्ट कार्यान्वयन का उपयोग करने के लिए मामला बना सकते हैं, तो एक सुअर पर लिपस्टिक लगाने की कोशिश न करें। आपको ए की जरूरत है LinkedHashMap, ए की नहींMap

इसने कहा, यदि आप प्रोग्रामिंग में नए हैं और इस उत्तर पर ठोकर खाते हैं, तो यह मत सोचिए कि यह आपको सर्वोत्तम अभ्यास के खिलाफ जाने की अनुमति देता है क्योंकि यह नहीं है। लेकिन जब दूसरे के लिए एक कार्यान्वयन की जगह स्वीकार्य नहीं है, तो केवल एक चीज जो आप कर सकते हैं वह है कि विशिष्ट कार्यान्वयन का उपयोग करें, और सोनार के लिए शापित हो।


1
व्यावहारिक दृष्टिकोण, जो मुझे पसंद है।
विदर्भ एस। रामदल

20
मैं जवाब से लगभग पूरी तरह सहमत हूं। मैं सिर्फ इतना कहूंगा कि आप सोनार के लिए अभिशप्त नहीं हैं। उस विशेष त्रुटि / चेतावनी को अनदेखा करने के लिए आप इसे हमेशा कॉन्फ़िगर कर सकते हैं। देखें stackoverflow.com/questions/10971968/…
व्लादिमीर स्टोक

11
if you are new to programming and stumble upon this answer, don't think this allows you to go against best practice because it doesn't.- अच्छी सलाह, अगर "सबसे अच्छा अभ्यास" जैसी कोई चीज थी। बेहतर सलाह: सही निर्णय लेना सीखें। यदि यह समझ में आता है, तो अभ्यास का पालन करें, लेकिन उपकरण और अधिकारियों को आपकी सोच प्रक्रिया का मार्गदर्शन करने दें, न कि इसे निर्देशित करें।
रॉबर्ट हार्वे

13
नोट: जब सोनार आपको कुछ रिपोर्ट करता है, तो आप इसे "हल नहीं किया जाएगा" के रूप में बंद कर सकते हैं और एक नोट छोड़ दें क्योंकि आप क्यों नहीं करेंगे। जैसे कि न केवल सोनार आपको परेशान करना बंद कर देगा, बल्कि आपको पता चल जाएगा कि आपने ऐसा क्यों किया।
वालफ्रैट

2
मुझे लगता है कि जो पहलू इसे सामान्य सिद्धांत का अपवाद बनाता है, वह यह है कि लिंक्डहाशपैप का एक अनुबंध है जो उस कार्यान्वयन के लिए विशिष्ट है और किसी भी इंटरफ़ेस में व्यक्त नहीं किया गया है। यह सामान्य मामला नहीं है। तो उस अनुबंध पर निर्भरता व्यक्त करने का एकमात्र तरीका कार्यान्वयन प्रकार का उपयोग करना है।
दना

21

आप तीन चीजों से लड़ रहे हैं:

सबसे पहले जावा का कंटेनर लाइब्रेरी है। इसकी वर्गीकरण में कुछ भी आपको यह निर्धारित करने का कोई तरीका नहीं देता है कि कक्षा एक पूर्वानुमानित क्रम में पुनरावृत्ति करती है या नहीं। ऐसा कोई IteratesInInsertedOrderMapइंटरफ़ेस नहीं है जिसे लागू किया जा सकता है LinkedHashMap, जो टाइपिंग जाँच (और उसी तरह का व्यवहार करने वाले वैकल्पिक कार्यान्वयन का उपयोग) को असंभव बनाता है। यह संभवतः डिजाइन द्वारा है, क्योंकि इसकी भावना यह है कि आप वास्तव में उन वस्तुओं से निपटने में सक्षम होने के लिए हैं जो सार की तरह व्यवहार करते हैं Map

दूसरा यह विश्वास है कि आपका लिंटर जो कहता है उसे सुसमाचार के रूप में माना जाना चाहिए और जो कुछ भी कहता है उसे अनदेखा करना बुरा है। इन दिनों अच्छे अभ्यास के लिए जो उत्तीर्ण होता है, उसके विपरीत, लिंटर चेतावनी को आपके कोड को अच्छा कहने में बाधा नहीं माना जाता है। वे आपके द्वारा लिखे गए कोड के बारे में तर्क करने का संकेत देते हैं और यह निर्धारित करने के लिए अपने अनुभव और निर्णय का उपयोग करते हैं कि क्या चेतावनी उचित है या नहीं। अन्यायपूर्ण चेतावनी है कि लगभग हर स्थैतिक विश्लेषण उपकरण यह बताने के लिए एक तंत्र प्रदान करता है कि आपने कोड की जांच की है, आपको लगता है कि आप जो कर रहे हैं वह ठीक है और उन्हें भविष्य में इसके बारे में शिकायत नहीं करनी चाहिए।

तीसरा, और यह शायद इसका मांस है, यह LinkedHashMapनौकरी के लिए गलत उपकरण हो सकता है। मैप्स यादृच्छिक के लिए अभिप्रेत हैं, आदेशित एक्सेस नहीं। यदि processData()बस क्रम में अभिलेखों पर पुनरावृत्ति होती है और कुंजी द्वारा अन्य अभिलेखों को खोजने की आवश्यकता नहीं है, तो आप a Mapका कार्य करने के लिए एक विशिष्ट कार्यान्वयन के लिए मजबूर कर रहे हैं List। दूसरी ओर, यदि आपको दोनों की आवश्यकता होती है, LinkedHashMapतो सही उपकरण है क्योंकि यह वह करने के लिए जाना जाता है जो आप चाहते हैं और आपको इसकी आवश्यकता से अधिक उचित है।


2
"LinkedHashMap कार्य के लिए गलत उपकरण हो सकता है"। हाँ शायद। जब मैं कहता हूं कि मुझे एक की जरूरत है OrderedMap, तो मैं भी कह सकता हूं UniqueList। जब तक यह एक परिभाषित पुनरावृत्ति क्रम के साथ किसी प्रकार का संग्रह है, जो सम्मिलित पर डुप्लिकेट को अधिलेखित करता है।
विदर्भ एस। रामदल

2
@ VidarS.Ramdal डेटाबेस क्वेरी डुप्लिकेट से बाहर निकलने के लिए आदर्श जगह होगी। यदि आपका डेटाबेस ऐसा नहीं कर सकता है, तो आप हमेशा Setसूची को बनाते समय केवल चाबियों का एक अस्थायी रख सकते हैं।
ब्लर एफएल

ओह, मैं देख रहा हूं कि मैंने भ्रम पैदा किया है। हां, डेटाबेस क्वेरी परिणाम में डुप्लिकेट शामिल नहीं है। लेकिन processDataनक्शे को संशोधित करता है, कुछ मूल्यों की जगह, कुछ नई कुंजी / मूल्यों को पेश करता है। तो processDataडुप्लिकेट का परिचय दे सकता है अगर यह एक के अलावा कुछ पर काम कर रहा था Map
विदर्भ एस। रामदल

7
@ VidarS.Ramdal: ऐसा लगता है कि आपको अपना खुद का UniqueList(या OrderedUniqueList) लिखना होगा और उसका उपयोग करना होगा। यह बहुत आसान है, और आपके इच्छित उपयोग को स्पष्ट करता है।
TMN

2
@TMN हां, मैंने उस दिशा में सोचना शुरू कर दिया है। यदि आप अपने सुझाव को उत्तर के रूप में पोस्ट करना चाहते हैं, तो यह निश्चित रूप से मेरा उत्थान होगा।
विदर्भ एस। रामदल

15

यदि आप सभी से प्राप्त LinkedHashMapकर रहे हैं List, तो डुप्लिकेट को अधिलेखित करने की क्षमता है, लेकिन आप वास्तव में इसे एक के रूप में उपयोग कर रहे हैं , तो मैं आपको अपने स्वयं के कस्टम Listकार्यान्वयन के साथ उस उपयोग को संप्रेषित करने का सुझाव दूंगा। आप इसे एक मौजूदा जावा संग्रह वर्ग पर आधारित कर सकते हैं addऔर removeअपने बैकिंग स्टोर को अपडेट करने के लिए किसी भी तरीके और तरीकों को ओवरराइड कर सकते हैं और विशिष्टता सुनिश्चित करने के लिए कुंजी का ट्रैक रख सकते हैं। इस तरह एक विशिष्ट नाम ProcessingListदेने से यह स्पष्ट हो जाएगा कि आपकी processDataपद्धति के लिए प्रस्तुत तर्क को एक विशेष तरीके से नियंत्रित करने की आवश्यकता है।


5
यह वैसे भी एक अच्छा विचार हो सकता है। हेक, आपके पास एक-लाइन फ़ाइल भी हो सकती है जो एक ProcessingListउपनाम के रूप में बनाता है LinkedHashMap- आप हमेशा इसे बाद में किसी और चीज़ से बदलने का फैसला कर सकते हैं, जब तक आप सार्वजनिक इंटरफ़ेस को बरकरार रखते हैं।
21

11

मैं आपको यह कहते हुए सुन रहा हूं कि "मेरे पास मेरे सिस्टम का एक हिस्सा है जो एक लिंक्डहाशमैप का उत्पादन करता है, और मेरी प्रणाली के एक अन्य हिस्से में मुझे केवल लिंक्डहैशपॉइंट ऑब्जेक्ट्स को स्वीकार करने की आवश्यकता है जो पहले भाग द्वारा उत्पादित किए गए थे, क्योंकि कुछ अन्य प्रक्रिया द्वारा उत्पादित लोग जीते गए ' t काम सही ढंग से। "

इससे मुझे लगता है कि वास्तव में यहाँ समस्या यह है कि आप लिंक्डहैशपॉप का उपयोग करने की कोशिश कर रहे हैं क्योंकि यह ज्यादातर आपके द्वारा खोजा जा रहा डेटा फिट बैठता है, लेकिन वास्तव में इसे आपके द्वारा बनाए गए किसी भी अन्य उदाहरण के साथ प्रतिस्थापित नहीं किया जा सकता है। जो आप वास्तव में करना चाहते हैं, वह अपना स्वयं का इंटरफ़ेस / वर्ग बनाना है जो आपका पहला भाग बनाता है और आपका दूसरा भाग उपभोग करता है। यह "वास्तविक" लिंक्डहैश मैप को लपेट सकता है, और एक मैप गेट्टर प्रदान कर सकता है या मैप इंटरफ़ेस लागू कर सकता है।

यह कैंडिडऑरेंज के उत्तर से थोड़ा अलग है, जिसमें मैं इसे विस्तारित करने के बजाय वास्तविक मानचित्र को एन्कैप्सुलेट करने (और आवश्यकतानुसार कॉल को सौंपने) की सिफारिश करूंगा। यह कभी-कभी उन शैली के पवित्र युद्धों में से एक है, लेकिन मुझे यकीन है कि यह "कुछ अतिरिक्त सामान के साथ एक नक्शा" नहीं है, यह "उपयोगी राज्य सूचना का मेरा बैग है, जिसे मैं आंतरिक रूप से एक मानचित्र के साथ प्रस्तुत कर सकता हूं"।

यदि आपके पास दो चर हैं जिन्हें आपको इस तरह से पास करने की आवश्यकता है, तो शायद आपने इसके बारे में ज्यादा विचार किए बिना इसके लिए एक वर्ग बनाया होगा। लेकिन कभी-कभी यह एक वर्ग के लिए उपयोगी होता है, भले ही यह सिर्फ एक सदस्य चर हो, सिर्फ इसलिए कि यह तार्किक रूप से एक ही बात है, "मूल्य" नहीं बल्कि "मेरे ऑपरेशन का नतीजा है कि मुझे बाद में चीजों को करने की आवश्यकता है"।


मुझे यह सोच पसंद है - मैं वहां गया हूं :) MyBagOfUsefulInformationइसे आबाद करने के लिए एक विधि (या निर्माता) की आवश्यकता होगी MyBagOfUsefulInformation.populate(SomeType data):। लेकिन dataहल किए गए क्वेरी परिणाम की आवश्यकता होगी। तो क्या होगा SomeType, यदि नहीं LinkedHashMap? मुझे यकीन नहीं है कि मैं इस कैच 22 को तोड़ पा रहा हूं।
विदुर एस। रामदल

MyBagOfUsefulInformationDAO या आपके सिस्टम में डेटा उत्पन्न करने वाले द्वारा क्यों नहीं बनाया जा सकता है? बैग के निर्माता और उपभोक्ता के बाहर आपको अपने बाकी कोड पर अंतर्निहित नक्शे को उजागर करने की आवश्यकता क्यों है?

आपकी वास्तुकला के आधार पर, आप यह सुनिश्चित करने के लिए एक निजी / संरक्षित / पैकेज-केवल निर्माता का उपयोग करने में सक्षम हो सकते हैं कि ऑब्जेक्ट केवल उस निर्माता द्वारा बनाया जा सकता है जिसे आप चाहते हैं। या आपको इसे एक सम्मेलन के रूप में करने की आवश्यकता हो सकती है, कि यह केवल सही "कारखाने" द्वारा बनाया जा सकता है।

हां, मैंने MyBagOfUsefulInformationDAO विधि के एक पैरामीटर के रूप में पास करके, कुछ इसी तरह का काम किया : softwareengineering.stackexchange.com/a/360079/52573
Vidar S. Ramdal

4

LinkedHashMap एकमात्र जावा मानचित्र है जिसमें प्रविष्टि क्रम की सुविधा है जिसे आप खोज रहे हैं। इसलिए डिपेंडेंसी इनवर्सन प्रिंसिपल को त्यागना लुभावना है और शायद व्यावहारिक भी। पहले, इस पर विचार करें कि इसका पालन करने के लिए क्या होगा। यहाँ क्या है SOLID करने के लिए आप से पूछना होगा।

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

public interface Ramdal {
    //ISP asks for just the methods that processData() actually uses.
    ...
}

public class RamdalLinkedHashMap extends LinkedHashMap implements Ramdal{} 

Ramdal<Key, Value> ramdal = new RamdalLinkedHashMap<>();

ramdal.put(key1, value1);
ramdal.put(key2, value2);

processData(ramdal);

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


2
मुझे नामकरण पसंद है!
विदर्भ एस। रामदल

1

बहुत अच्छे सुझाव के लिए धन्यवाद और विचार के लिए भोजन।

मैंने एक नया मैप क्लास बनाते हुए विस्तार किया, processDataएक उदाहरण विधि:

class DataMap extends LinkedHashMap<Key, Value> {

   processData();

}

तब मैंने डीएओ पद्धति को फिर से लागू किया ताकि यह एक नक्शा न लौटे, लेकिन इसके बजाय targetपैरामीटर के रूप में एक नक्शा लेता है :

public void fetchData(Map<Key, Value> target) {
  ...
  // for each result row
  target.put(key, value);
}

इसलिए DataMapडेटा को पॉप्युलेट करना और प्रोसेस करना अब दो चरणों वाली प्रक्रिया है, जो ठीक है, क्योंकि कुछ अन्य चर हैं जो एल्गोरिथम का हिस्सा हैं, जो अन्य स्थानों से आता है।

public DataMap fetchDataMap() {
  var dataMap = new DataMap();
  dao.fetchData(dataMap);
  return dataMap;
}

यह मेरे मानचित्र कार्यान्वयन को नियंत्रित करने की अनुमति देता है कि प्रविष्टियां इसमें कैसे डाली जाती हैं, और आदेश की आवश्यकता को दूर कर देती है - यह अब कार्यान्वयन विवरण है DataMap


0

यदि आप संवाद करना चाहते हैं कि आपके द्वारा उपयोग की जाने वाली डेटा संरचना एक कारण के लिए है, तो विधि के हस्ताक्षर के ऊपर एक टिप्पणी जोड़ें। यदि भविष्य में कोई अन्य डेवलपर कोड की इस पंक्ति में आता है और टूल चेतावनी को नोटिस करता है, तो वे टिप्पणी को नोटिस कर सकते हैं और समस्या को "ठीक करने" से मना कर सकते हैं। यदि कोई टिप्पणी नहीं है, तो उन्हें हस्ताक्षर बदलने से कुछ भी नहीं रोका जाएगा।

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


0

इसलिए, मुझे यहाँ अपना संदर्भ समझने की कोशिश करें:

... सम्मिलन आदेश मायने रखता है ... नक्शे को क्रमबद्ध करना एक भारी ऑपरेशन होगा ...

... क्वेरी परिणाम पहले से ही जिस तरह से मैं चाहता हूं, उसे क्रमबद्ध किया गया है

अब, आप वर्तमान में क्या कर रहे हैं:

मैं डेटाबेस से tuples का एक सेट ला रहा हूं, और इसे एक मानचित्र में डाल रहा हूं ...

और यहां आपका वर्तमान कोड है:

public void processData(LinkedHashMap<Key, Value> data) {...}

मेरा सुझाव निम्न कार्य करना है:

  • निर्भरता इंजेक्शन का उपयोग करें और कुछ MyTupleRepository को प्रसंस्करण विधि में इंजेक्ट करें (MyTupleRepository एक इंटरफ़ेस है जो उन वस्तुओं द्वारा कार्यान्वित किया जाता है जो आपके tuple ऑब्जेक्ट्स को आमतौर पर DB से प्राप्त करते हैं);
  • के भीतर से प्रसंस्करण विधि के लिए, विशिष्ट लिंक्डहाशप संग्रह में रिपॉजिटरी (उर्फ डीबी, जो पहले से ही ऑर्डर किए गए डेटा लौटाता है) से डेटा डालते हैं, क्योंकि यह प्रोसेसिंग एल्गोरिथ्म का आंतरिक विवरण है (क्योंकि यह इस बात पर निर्भर करता है कि डेटा संरचना में डेटा की व्यवस्था कैसे की जाती है। );
  • ध्यान दें, यह बहुत ज्यादा है जो आप पहले से कर रहे हैं, लेकिन इस मामले में यह प्रसंस्करण विधि के भीतर किया जाएगा। आपकी रिपॉजिटरी को कहीं और इंस्टेंट किया गया है (आपके पास पहले से ही एक वर्ग है जो डेटा लौटाता है, यह इस उदाहरण में रिपॉजिटरी है)

कोड उदाहरण

public interface MyTupleRepository {
    Collection<MyTuple> GetAll();
}

//Concrete implementation of data access object, that retrieves 
//your tuples from DB; this data is already ordered by the query
public class DbMyTupleRepository implements MyTupleRepository { }

//Injects some abstraction of repository into the processing method,
//but make it clear that some exception might be thrown if data is not
//arranged in some specific way you need
public void processData(MyTupleRepository tupleRepo) throws DataNotOrderedException {

    LinkedHashMap<Key, Value> data = new LinkedHashMap<Key, Value>();

    //Represents the query to DB, that already returns ordered data
    Collection<MyTuple> myTuples = tupleRepo.GetAll();

    //Optional: this would throw some exception if data is not ordered 
    Validate(myTuples);

    for (MyTupleData t : myTuples) {
        data.put(t.key, t.value);
    }

    //Perform the processing using LinkedHashMap...
    ...
}

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


हम्म, लेकिन रिपॉजिटरी को कैसे तत्काल किया जाएगा? क्या यह सिर्फ समस्या को कहीं और नहीं ले जाएगा (जहां MyTupleRepositoryबनाया गया है?)
विदुर एस। रामदल

मुझे लगता है कि मैं पीटर कूपर के जवाब के साथ उसी समस्या में चलूंगा
विदर्भ एस। रामदल

मेरे सुझाव में डिपेंडेंसी इंजेक्शन सिद्धांत लागू करना शामिल है; इस उदाहरण में; MyTupleRepository एक इंटरफ़ेस है जो आपके द्वारा बताए गए tuples को पुनर्प्राप्त करने की क्षमता को परिभाषित करता है (जो DB प्रश्न करता है)। यहां, आप इस ऑब्जेक्ट को प्रोसेसिंग विधि में इंजेक्ट करते हैं। आपके पास पहले से ही कुछ वर्ग हैं जो डेटा लौटाते हैं; यह केवल एक इंटरफेस में इसे अमूर्त करता है, और आप ऑब्जेक्ट को 'प्रोसेसडाटा' विधि में इंजेक्ट करते हैं, जो आंतरिक रूप से लिंक्डहैश मैप का उपयोग करता है क्योंकि यह आंतरिक रूप से प्रसंस्करण का हिस्सा है।
एमर्सन कार्डसो

मैंने अपना जवाब संपादित किया, जो मैं सुझाव दे रहा हूं, उसके बारे में अधिक स्पष्ट होने की कोशिश कर रहा हूं।
एमर्सन कार्डसो

-1

यह प्रश्न वास्तव में आपके डेटा मॉडल के एक में लुढ़कने के मुद्दों का एक गुच्छा है। आपको उन्हें एक समय में एक करने की आवश्यकता है। जैसा कि आप पहेली के प्रत्येक टुकड़े को सरल बनाने की कोशिश करते हैं, अधिक प्राकृतिक, सहज समाधान निकल जाएंगे।

समस्या 1: आप DB ऑर्डर पर निर्भर नहीं रह सकते

आपके डेटा को सॉर्ट करने के आपके विवरण स्पष्ट नहीं हैं।

  • सबसे बड़ी संभावित समस्या यह है कि आप अपने डेटाबेस में एक ORDER BYखंड के माध्यम से एक स्पष्ट प्रकार निर्दिष्ट नहीं कर रहे हैं । यदि आप नहीं कर रहे हैं क्योंकि यह बहुत महंगा लगता है, तो आपके प्रोग्राम में बग है । यदि आप एक निर्दिष्ट नहीं करते हैं तो डेटाबेस को किसी भी क्रम में परिणाम वापस करने की अनुमति है ; आप इस पर निर्भर नहीं कर सकते कि संयोग से डेटा वापस आ रहा है सिर्फ इसलिए कि आपने क्वेरी को कुछ बार चलाया और यह इस तरह दिखता है। आदेश बदल सकता है क्योंकि डिस्क पर पंक्तियों को फिर से व्यवस्थित किया जाता है, या कुछ हटा दिए जाते हैं और नए लोग अपनी जगह लेते हैं, या एक सूचकांक जोड़ा जाता है। आपको किसी प्रकार का एक खंड निर्दिष्ट करना होगा ORDER BY। गति बिना शुद्धता के बेकार है।
  • यह भी स्पष्ट नहीं है कि आप सम्मिलन आदेश से क्या मतलब है। यदि आप स्वयं डेटाबेस के बारे में बात कर रहे हैं, तो आपके पास एक कॉलम होना चाहिए जो वास्तव में इसे ट्रैक करता है, और इसे आपके क्लॉज़ में शामिल किया जाना चाहिए ORDER BY। अन्यथा, आपके पास कीड़े हैं। यदि ऐसा कॉलम अभी तक मौजूद नहीं है, तो आपको एक जोड़ने की आवश्यकता है। इस तरह के कॉलम के लिए विशिष्ट विकल्प एक प्रविष्टि टाइमस्टैम्प कॉलम या एक ऑटो-इंक्रीमेंटिंग कुंजी होगी। ऑटो-इन्क्रिमेंटिंग कुंजी अधिक विश्वसनीय है।

समस्या 2: स्मृति क्रमबद्ध बनाना कुशल

एक बार जब आप यह सुनिश्चित कर लें यह है की गारंटी प्रकार आदेश जैसा कि आप उम्मीद, आप स्मृति में बनाने के लिए इस तथ्य का लाभ उठा सकते में डेटा लौट करने के लिए बहुत अधिक कुशल। बस एक जोड़ेंrow_number() याdense_rank() आपकी क्वेरी के परिणाम सेट करने के लिए स्तंभ (या अपने डेटाबेस के समकक्ष)। अब प्रत्येक पंक्ति में एक सूचकांक होता है जो आपको प्रत्यक्ष संकेत देगा कि आदेश क्या माना जाता है, और आप इसे स्मृति में तुच्छ रूप से क्रमबद्ध कर सकते हैं। बस सुनिश्चित करें कि आप सूचकांक को एक सार्थक नाम (जैसे sortedBySomethingIndex) दें।

वियोला। अब आपको डेटाबेस परिणाम सेट आदेश पर निर्भर नहीं रहना होगा।

समस्या 3: क्या आपको यह प्रक्रिया कोड में भी करने की आवश्यकता है?

एसक्यूएल वास्तव में है शक्तिशाली है। यह एक अद्भुत घोषणात्मक भाषा है जो आपको अपने डेटा पर बहुत सारे परिवर्तन और एकत्रीकरण करने देती है। अधिकांश डीबी आजकल क्रॉस पंक्ति संचालन का भी समर्थन करते हैं। वे खिड़की या विश्लेषणात्मक कार्य कहलाते हैं:

क्या आपको भी अपने डेटा को इस तरह मेमोरी में खींचने की ज़रूरत है? या आप विंडो फ़ंक्शन का उपयोग करके SQL क्वेरी में सभी काम कर सकते हैं? यदि आप DB में काम के सभी (या शायद सिर्फ एक महत्वपूर्ण हिस्सा) कर सकते हैं, तो शानदार! आपकी कोड समस्या दूर हो जाती है (या बहुत सरल हो जाती है)!

समस्या 4: आप क्या कर रहे हैं data?

यह मानते हुए कि आप DB में यह सब नहीं कर सकते हैं, मुझे इसे सीधे करने दें। आप डेटा को मानचित्र के रूप में ले रहे हैं (जो कि उन चीजों से जुड़ा हुआ है जिन्हें आप क्रमबद्ध नहीं करना चाहते हैं), फिर आप इस पर ध्यान केंद्रित कर रहे हैं प्रविष्टि क्रम , और कुछ चाबियों का मूल्य की जगह और जोड़कर जगह में नक्शे को संशोधित एक नए?

मैं माफी चाहता हूँ, लेकिन क्या बिल्ली?

कॉल करने वालों को इस सब के बारे में चिंता करने की ज़रूरत नहीं होनी चाहिए । आपके द्वारा बनाया गया सिस्टम अत्यंत है नाजुक है। यह केवल एक गूंगा गलती लेता है (शायद अपने आप से भी, जैसा कि हम सभी ने किया है) एक छोटे से गलत बदलाव के लिए और पूरी चीज ताश के पत्तों की तरह ढह जाती है।

यहाँ शायद एक बेहतर विचार है:

  • क्या आपका कार्य स्वीकार है List
  • कुछ तरीके हैं जिनसे आप ऑर्डर करने की समस्या को संभाल सकते हैं।
    1. फेल फास्ट अप्लाई करें। यदि फ़ंक्शन को आवश्यकता होती है तो सूची में त्रुटि नहीं है। (नोट: आप समस्या 2 से सॉर्ट इंडेक्स का उपयोग यह बताने के लिए कर सकते हैं कि यह है।)
    2. अपने आप को एक क्रमबद्ध प्रतिलिपि बनाएँ (फिर समस्या 2 से सूचकांक का उपयोग करके)।
    3. क्रम में नक्शा खुद बनाने के लिए एक तरह से चित्रा।
  • आंतरिक रूप से फ़ंक्शन के लिए आवश्यक मानचित्र का निर्माण करें, इसलिए कॉलर को इसकी परवाह नहीं करनी चाहिए।
  • अब आपके पास जो भी आदेश प्रतिनिधित्व है उस पर पुनरावृति करें और जो आपके पास है उसे करें।
  • नक्शा लौटाएँ, या इसे उचित वापसी मूल्य में बदलें

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

या शायद यह अधिक समझ में आता है: dataपैरामीटर से छुटकारा पाएं और processDataवास्तव में अपना डेटा प्राप्त करें। तब आप यह दस्तावेज़ कर सकते हैं कि आप ऐसा कर रहे हैं, क्योंकि इसमें उस डेटा की बहुत विशिष्ट आवश्यकताएं हैं जिस पर डेटा प्राप्त होता है। दूसरे शब्दों में, फंक्शन को अपना बनाएं को पूरी प्रक्रिया का , न कि केवल इसका एक टुकड़ा; अंतर-निर्भरताएं तर्क को छोटे टुकड़ों में विभाजित करने के लिए बहुत मजबूत हैं। (प्रक्रिया में फ़ंक्शन का नाम बदलें।)

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

सारांश

मुझे लगता है कि यहां समस्या अंततः यह है कि शैतान विवरण में है। जब मैं इस तरह से मुसीबत में दौड़ना शुरू करता हूं, तो यह आमतौर पर होता है क्योंकि मेरे पास वास्तव में हल करने की कोशिश कर रहे समस्या के लिए मेरे डेटा का अनुचित प्रतिनिधित्व है । सबसे अच्छा समाधान एक बेहतर प्रतिनिधित्व है , और फिर मेरी समस्या को हल करने के लिए सरल (शायद आसान नहीं है, लेकिन सीधा) हो जाता है।

किसी ऐसे व्यक्ति को खोजें जो उस बिंदु को प्राप्त करता है: आपका काम आपकी समस्या को सरल, सीधे लोगों के एक समूह में कम करना है। तब आप मजबूत, सहज ज्ञान युक्त कोड बना सकते हैं। उनसे बात करो। अच्छा कोड और अच्छा डिज़ाइन आपको लगता है कि कोई भी बेवकूफ उन्हें सोच सकता था, क्योंकि वे सरल और सीधे हैं। हो सकता है कि एक वरिष्ठ डेवलपर है जिसके पास वह मानसिकता है जिससे आप बात कर सकते हैं।


"आपका क्या मतलब है कि कोई प्राकृतिक आदेश नहीं है, लेकिन सम्मिलन आदेश मायने रखता है? क्या आप कह रहे हैं कि यह मायने रखता है कि डीबी तालिका में डेटा किस क्रम में डाला गया था, लेकिन आपके पास कोई कॉलम नहीं है जो आपको बता सके कि किस क्रम में चीजें डाली गई थीं?" - यह प्रश्न बताता है: "मानचित्र को क्रमबद्ध करना एक भारी ऑपरेशन होगा, इसलिए मैं ऐसा करने से बचना चाहता हूं, यह देखते हुए कि क्वेरी परिणाम पहले से ही हल हो गया है"। यह स्पष्ट रूप से मतलब है कि वहाँ है डेटा के लिए एक calculatable निश्चित क्रम, क्योंकि अन्यथा यह छँटाई बल्कि भारी से असंभव हो जाएगा, लेकिन यह परिभाषित आदेश चाबियों का प्राकृतिक व्यवस्था के लिए अलग है।
जूल्स

2
दूसरे शब्दों में, ओपी एक क्वेरी के परिणामों पर काम कर रहा है जैसे select key, value from table where ... order by othercolumn, और उनके प्रसंस्करण में ऑर्डर बनाए रखने की आवश्यकता होती है। जिस प्रविष्टि क्रम का वे उल्लेख कर रहे हैं, वह उनके नक्शे में प्रविष्टि क्रम है , जो उनके क्वेरी में उपयोग किए गए आदेश द्वारा परिभाषित किया गया है, डेटाबेस में प्रविष्टि क्रम नहीं । यह उनके उपयोग द्वारा स्पष्ट किया जाता है LinkedHashMap, जो कि एक डेटा संरचना है जिसमें Mapएक Listके-वैल्यू जोड़े के दोनों की विशेषताएं हैं ।
जूल्स

@ जूल्स मैं उस खंड को थोड़ा साफ करूँगा, धन्यवाद। (मुझे वास्तव में यह पढ़कर याद आया, लेकिन जब मैं प्रश्न लिखते समय चीजों की जाँच कर रहा था, तो मैं इसे नहीं ढूंढ सका। क्वेरी और उनके पास एक स्पष्ट प्रकार है या नहीं। वे यह भी कहते हैं कि "सम्मिलन आदेश मायने रखता है।" मुद्दा यह है कि भले ही छंटाई भारी हो, आप स्पष्ट रूप से नहीं बताने पर डीबी पर सिर्फ जादुई तरीके से चीजों को सही ढंग से क्रमबद्ध करने के लिए भरोसा नहीं कर सकते। और अगर आप इसे डीबी में कर रहे हैं, तो आप इसे कोड में कुशल बनाने के लिए "इंडेक्स" का उपयोग कर सकते हैं।
jpmc26

* उत्तर लिखना (मैथिंक मैं जल्द ही बिस्तर पर जाना चाहिए।)
jpmc26

हां, @ जूल्स सही हैं। वहाँ है एक order byक्वेरी में खंड, लेकिन यह गैर तुच्छ (है नहीं बस order by column,) तो मैं जावा में छँटाई reimplementing बचना चाहते हैं। हालांकि एसक्यूएल है शक्तिशाली (और हम एक Oracle 11g डेटाबेस के बारे में यहाँ बात कर रहे हैं), की प्रकृति processDataएल्गोरिथ्म यह बहुत आसान जावा में व्यक्त करने के लिए बनाता है। और हाँ, "प्रविष्टि क्रम" का अर्थ है " मानचित्र प्रविष्टि क्रम", अर्थात क्वेरी परिणाम क्रम।
विदर्भ एस। रामदल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.