2009-02-23 10 views
9

मान लीजिए कि आपके पास एक ही बीन प्रकार के दो उदाहरण हैं, और आप दो उदाहरणों के बीच क्या बदल गए हैं इसका एक सारांश प्रदर्शित करना चाहते हैं - उदाहरण के लिए, आपके पास आपके आवेदन में उपयोगकर्ता की सेटिंग्स का प्रतिनिधित्व करने वाला एक बीन है, और आप ' डी उपयोगकर्ता द्वारा सबमिट की जाने वाली नई सेटिंग्स में जो बदलाव आया है उसकी एक सूची प्रदर्शित करने में सक्षम होना (उदाहरण # 1) बनाम उपयोगकर्ता के लिए पहले से संग्रहीत किया गया है (उदाहरण # 2)।दो सेम में खेतों के एक diff पैदा करने के लिए आम एल्गोरिदम?

क्या इस तरह के कार्य के लिए आमतौर पर उपयोग किया जाने वाला एल्गोरिदम या डिज़ाइन पैटर्न होता है, शायद कुछ ऐसा जो कि विभिन्न प्रकार के सेम के लिए सारणित और पुन: उपयोग किया जा सकता है? (मुझे इस बात की समस्या के लिए एक अच्छा नाम सोचने में कठिनाई हो रही है कि Google को क्या पता है)। मैंने कॉमन्स-बीनटिल की जांच की है और मुझ पर कुछ भी नहीं निकला है।

उत्तर

6

यदि आप मूल्यों की तुलना करने के बारे में बात कर रहे हैं, तो मैं प्रतिबिंब का उपयोग करने और फ़ील्ड द्वारा उन्हें फ़ील्ड की तुलना करने पर विचार करता हूं।

कुछ इस तरह:


    Field[] oldFields = oldInstance.class.getDeclaredFields(); 
    Field[] newFields = newInstance.class.getDeclaredFields(); 
    StringBuilder changes = new StringBuilder(); 

    Arrays.sort(oldFields); 
    Arrays.sort(newFields); 

    int i = 0; 
    for(Field f : oldFields) 
    { 
     if(!f.equals(newFields[i])) 
     { 
      changes.append(f.getName()).append(" has changed.\n"); 
     } 
     i++; 
    } 

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

+0

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

+0

वे दोनों एक ही कक्षा के उदाहरण हैं, उनकी संख्या कितनी अलग हो सकती है? – kgrad

+0

इसके अलावा, यदि यह एकल-थ्रेडेड है, तो आपको स्ट्रिंगबफर के बजाय स्ट्रिंगबिल्डर का उपयोग करना चाहिए। – cdmckay

2

प्रतिबिंब अगली कॉलिंग में फ़ील्ड का क्रम नहीं रखता है: यह सरणी को सुरक्षित आदेश देता है।

/* 
*declarations of variables 
*/ 

Arrays.sort(oldFields);//natural order - choice 1 
Arrays.sort(newFields, new Ordinator());//custom Comparator - choice 2 

/* 
*logic of comparations between elements 
*/ 

विकल्प 2 में आप छँटाई एक आंतरिक वर्ग Ordinator extending Comparator साथ (कैसे तत्व सॉर्ट करेंगे) के तर्क तय कर सकते हैं।

पुनश्च कोड एक मसौदा

3

हम सेम utils के साथ कुछ ऐसा ही किया है और यह अच्छी तरह से काम करता है। विचार करने वाली चीजें: क्या आप फील्ड ऑब्जेक्ट्स में ड्रिल करते हैं - यदि किसी व्यक्ति में कोई पता होता है और पता बदलता है तो क्या आप कहते हैं कि पता बदल गया है या पता.postalCode बदल गया है (हम करते हैं)? क्या आप एक सूची प्रोपेटी नाम, पुराना मान, diff से नए मान (हम करते हैं) वापस करते हैं? आप तिथियों को कैसे संभालना चाहते हैं - यदि आप जिसकी देखभाल करते हैं, वह तारीख का हिस्सा है तो आपकी तुलना उस समय को अनदेखा करनी चाहिए? आप कैसे कहते हैं कि किन क्षेत्रों को अनदेखा करना है?

यह वास्तव में एक प्रतिलिपि और पेस्ट उत्तर नहीं है, लेकिन चीजों की सूची में से अधिक है जो हमारे अलग-अलग लिखते समय तत्काल स्पष्ट नहीं थे।

कार्यान्वयन के लिए, हमारे पास केवल एक स्थिर उपयोग विधि है जो तुलना करने के लिए दो सेम और गुणों की एक सूची लेती है और फिर पुराने मूल्य और नए मान वाले जोड़े में गुणों का नक्शा देता है। फिर प्रत्येक बीन में diff(Object o) विधि होती है जो स्थिर उपयोग विधि को आवश्यकतानुसार कॉल करती है।

+0

मैं एक समान आवश्यकता पर काम कर रहा हूं। आपके द्वारा उल्लिखित समाधान दिलचस्प लग रहा है। क्या आप कोड या एल्गोरिदम विवरण साझा करने में सक्षम होंगे? धन्यवाद। – krishnakumarp

+1

मेरी इच्छा है कि मैं कर सकता हूं, लेकिन यह दो नौकरियां थीं। हालांकि, मैंने दो साल पहले एक साक्षात्कार के लिए 'प्रेरित' नमूना कोड लिखा था। यह मूल के रूप में ज्यादा नहीं करता है, लेकिन प्रेरणा के लिए उपयोगी हो सकता है। [इसे डाउनलोड करें] (http://stanford.edu/~pradtke/ObjectDiffer.zip) या [ब्राउज़ करें] (http://stanford.edu/~pradtke/ObjectDiffer/)। – Patrick

1

ऊपर अच्छे उत्तरों।

यदि आपका डेटा संरचनात्मक रूप से बदलता है, यानी फ़ील्ड का पूरा संग्रह प्रासंगिक हो सकता है या दूसरों के आधार पर नहीं, तो आप differential execution पर विचार करना चाहेंगे।

असल में, आपके पास फ़ील्ड पर एक लूप है, और आप उसी समय मौजूदा फ़ील्ड मानों को क्रमबद्ध करते हैं जैसे आप पूर्व मानों को deserialize करते हैं, जैसा कि आप जाते हैं उन्हें तुलना करते हैं।

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

बस एक सुझाव।

+0

लिंक के लिए धन्यवाद, मैं निश्चित रूप से इसमें देख लूंगा –

3

इन पुस्तकालयों को मदद करनी चाहिए।

https://code.google.com/p/beandiff/ - एक एनोटेशन आधारित बीन diffing पुस्तकालय। अपाचे लाइसेंस 2.0

https://github.com/SQiShER/java-object-diff/ - एक बीन विज़िटर पैटर्न के आधार पर भिन्न होता है। अपाचे लाइसेंस 2.0

हमें ऑडिटिंग उद्देश्य के लिए जेसन प्रारूप में बीन्स के बीच अंतर उत्पन्न करने की आवश्यकता थी। हमने इसे beandiff लाइब्रेरी का उपयोग करके कार्यान्वित कर दिया।

** संपादित करें ** यह एक नया विकल्प जैसा दिखता है। मैंने हालांकि इसका इस्तेमाल नहीं किया है।

http://beandiff.org/

आशा है कि यह मदद करता है।

0

प्रतिबिंब और मानक डेटा संरचनाओं का उपयोग समाधान।

Field[] declaredFields = ClassOne.class.getDeclaredFields(); 
    Field[] declaredFields2 = ClassTwo.class.getDeclaredFields(); 
    ArrayList<String> one = new ArrayList<String>(); 
    ArrayList<String> two = new ArrayList<String>(); 
    for (Field field : declaredFields) 
    { 
     one.add(field.getName()); 
    } 

    for (Field field : declaredFields2) 
    { 
     two.add(field.getName()); 
    } 

    List<String> preone = (List<String>)one.clone(); 

    one.removeAll(two); 
    two.removeAll(preone); 
    Collections.sort(one); 
    Collections.sort(two); 

    System.out.println("fields only in One : " + one); 
    System.out.println("fields only in Two : " + two); 
संबंधित मुद्दे