2012-10-17 24 views
8

जावा में लिखी एक मौजूदा प्रणाली लोड संतुलन के लिए अपनी रूटिंग रणनीति के रूप में एक स्ट्रिंग के हैशकोड का उपयोग करती है।जावा में एक ही हैशकोड साझा करने वाले तारों को कैसे उत्पन्न करें?

अब, मैं सिस्टम को संशोधित नहीं कर सकता, लेकिन सबसे खराब स्थिति का परीक्षण करने के लिए समान हैशकोड साझा करने वाले तारों को उत्पन्न करने की आवश्यकता है।

मैं उन तारों को कमांडलाइन से प्रदान करता हूं और उम्मीद करता हूं कि सिस्टम इन सभी तारों को उसी गंतव्य में रूट करेगा।

क्या एक ही हैशकोड साझा करने वाली बड़ी संख्या में स्ट्रिंग उत्पन्न करना संभव है?

String[] getStringsInSameHashCode(int number){ 
    //return an array in length "number" 
    //Every element of the array share the same hashcode. 
    //The element should be different from each other 
} 

टिप्पणी::

इस सवाल का स्पष्ट करने के लिए किसी भी hashCode मूल्य स्वीकार्य है। स्ट्रिंग क्या है इस पर कोई बाधा नहीं है। लेकिन वे एक-दूसरे से अलग होना चाहिए।

संपादित करें: स्ट्रिंग क्लास की ओवरराइड विधि स्वीकार्य नहीं है क्योंकि मैं कमांड लाइन से उन स्ट्रिंग को खिलाता हूं।

इंस्ट्रुमेंटेशन भी स्वीकार्य नहीं है क्योंकि इससे सिस्टम पर कुछ प्रभाव पड़ेगा।

+0

बराबर स्ट्रिंग का उपयोग कर एक विकल्प नहीं है? –

+0

स्ट्रिंग स्रोत कोड देखें। –

+0

क्या उन्हें अलग-अलग मूल्यों या सिर्फ अलग स्ट्रिंग ऑब्जेक्ट्स के साथ स्ट्रिंग होने की आवश्यकता है? –

उत्तर

17

जब से तुम चीनी आप इतने लंबे समय के रूप में आप से मेल खाते हैं, मेरी पोस्ट http://www.hetaoblog.com/myblogs/post/%E8%AF%B4%E4%B8%80%E8%AF%B4java%E9%87%8C%E9%9D%A2%E7%9A%84hashcode-string-hashcode.jhtml

एक परीक्षा पद्धति, मूल रूप से देख देख सकते हैं पढ़ सकते हैं, A1 * 31 + बी 1 = A2 * 31 + b2, जिसका अर्थ है (a1-A2) * 31 = B2-बी 1

public void testHash() 
{ 
    System.out.println("A:" + ((int)'A')); 
    System.out.println("B:" + ((int)'B')); 
    System.out.println("a:" + ((int)'a')); 

    System.out.println(hash("Aa".hashCode())); 
    System.out.println(hash("BB".hashCode())); 
    System.out.println(hash("Aa".hashCode())); 
    System.out.println(hash("BB".hashCode())); 


    System.out.println(hash("AaAa".hashCode())); 
    System.out.println(hash("BBBB".hashCode())); 
    System.out.println(hash("AaBB".hashCode())); 
    System.out.println(hash("BBAa".hashCode())); 

} 

आप मिल जाएगा

A:65 
B:66 
a:97 
2260 
2260 
2260 
2260 
2019172 
2019172 
2019172 
2019172 

संपादित करें: किसी ने कहा कि यह नहीं है काफी सरल है।मैं हिस्सा नीचे जुड़ते

@Test 
    public void testN() throws Exception { 
     List<String> l = HashCUtil.generateN(3); 
     for(int i = 0; i < l.size(); ++i){ 
      System.out.println(l.get(i) + "---" + l.get(i).hashCode()); 
     } 
    } 
AaAaAa---1952508096 
AaAaBB---1952508096 
AaBBAa---1952508096 
AaBBBB---1952508096 
BBAaAa---1952508096 
BBAaBB---1952508096 
BBBBAa---1952508096 
BBBBBB---1952508096 
नीचे

है स्रोत कोड, यह कुशल नहीं हो सकता है, लेकिन यह काम करते हैं: String.hashCode()

public int hashCode() { 
    int h = hash; 
    if (h == 0) { 
     int off = offset; 
     char val[] = value; 
     int len = count; 

      for (int i = 0; i < len; i++) { 
       h = 31*h + val[off++]; 
      } 
      hash = h; 
     } 
     return h; 
    } 
+0

अच्छा, यह ठीक है अगर यह एसओ का नियम या संस्कृति है जो अंग्रेजी को केवल लिंक प्रदान करता है ... मैं सिर्फ लेखक को और अधिक प्रदान करना चाहता हूं; जबकि समस्या के लिए, मुझे लगता है कि मैंने डेमो कोड और कुछ शब्दों का उपयोग करके पर्याप्त समझाया है ... – hetaoblog

+0

1) हां यह है। 2) डेमो कोड और शब्द वास्तव में सवाल का जवाब नहीं देते हैं। प्रश्न ** ** टकराव उत्पन्न करने के तरीके के बारे में है। टक्कर कैसे होती है/क्यों प्रासंगिक नहीं है इसका एक स्पष्टीकरण प्रासंगिक नहीं है। –

+0

मुझे लगता है कि यह एक बहुत अच्छा जवाब है, हालांकि उत्पन्न होने वाली स्ट्रिंग बहुत लंबी है यदि एन बहुत बड़ा है। – StarPinkER

0
String s = "Some String" 
for (int i = 0; i < SOME_VERY_BIG_NUMBER; ++i) { 
    String copy = new String(s); 

    // Do something with copy. 
} 

क्या यह आपके लिए काम करेगा? यह सिर्फ उसी स्ट्रिंग अक्षर की बहुत सारी प्रतियां बनाता है जिसे आप अपने परीक्षण में उपयोग कर सकते हैं।

+0

क्षमा करें मैंने इसे पर्याप्त स्पष्ट नहीं किया है। समान स्ट्रिंग अक्षर स्वीकार्य नहीं है, क्योंकि डेटाबेस में स्ट्रिंग प्राथमिक कुंजी है, मुझे अलग-अलग स्ट्रिंग अक्षर की आवश्यकता है। – StarPinkER

1

आप java.lang.String क्लास को वाद्य यंत्र बना सकते हैं, इसलिए इसकी विधि हैशकोड() हमेशा एक ही संख्या को वापस कर देगी।

मुझे लगता है कि जावस्सिस्ट ऐसा उपकरण करने का सबसे आसान तरीका है।

संक्षेप में:

  • एक जावा-एजेंट का उपयोग करके java.lang.instrument.Instrumentation का एक उदाहरण प्राप्त इंस्ट्रूमेंटेशन का उपयोग करके (विवरण के लिए package java.lang.instrument documentation देखें)
  • को फिर से परिभाषित java.lang.String वर्ग। redefineClasses (ClassDefinition []) विधि

कोड की तरह (मोटे तौर पर) दिखेगा:

ClassPool classPool = new ClassPool(true); 
CtClass stringClass = classPool.get("java.lang.String"); 
CtMethod hashCodeMethod = stringClass.getDeclaredMethod("hashCode", null); 
hashCodeMethod.setBody("{return 0;}"); 
byte[] bytes = stringClass.toBytecode(); 
ClassDefinition[] classDefinitions = new ClassDefinition[] {new ClassDefinition(String.class, bytes); 
instrumentation.redefineClasses(classDefinitions);// this instrumentation can be obtained via Java-agent 

यह भी न भूलें कि एजेंट प्रकट फ़ाइल को redefineClasses (क्लासडिफिनिशन []) विधि का उपयोग करने में सक्षम होने के लिए Can-Redefine-Classes: true निर्दिष्ट करना होगा।

+0

आपके उत्तर के लिए धन्यवाद। हैशकोड विधि को ओवरराइड करना स्वीकार्य नहीं है क्योंकि यह सिस्टम को प्रभावित करेगा। परिदृश्य मुझे उन स्ट्रिंग अक्षर के साथ सिस्टम का परीक्षण करने की आवश्यकता है। सिस्टम पर संशोधन निश्चित रूप से अस्वीकार्य है। – StarPinkER

+0

@ जर्मेन Xu, यह ओवरराइड नहीं है, लेकिन वाद्ययंत्र। हालांकि हां आपको "जावा में लिखी गई मौजूदा प्रणाली" के साथ जेवीएम को फिर से लॉन्च करने की क्षमता की आवश्यकता है और कमांड लाइन तर्कों के माध्यम से एक एजेंट को JVM में जोड़ें। तो यदि आप ऐसा नहीं कर सकते हैं, तो मेरा सुझाव अनुपयोगी है। इस मामले में "हेटाब्लॉग" का जवाब आपकी स्थिति में फिट होना चाहिए :) – Male

+0

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

5

मैं कम से

public class HashCUtil { 

    private static String[] base = new String[] {"Aa", "BB"}; 

    public static List<String> generateN(int n) 
    { 
     if(n <= 0) 
     { 
      return null; 
     } 

     List<String> list = generateOne(null); 
     for(int i = 1; i < n; ++i) 
     { 
      list = generateOne(list); 
     } 

     return list; 
    } 


    public static List<String> generateOne(List<String> strList) 
    { 
     if((null == strList) || (0 == strList.size())) 
     { 
      strList = new ArrayList<String>(); 
      for(int i = 0; i < base.length; ++i) 
      { 
       strList.add(base[i]); 
      } 

      return strList; 
     } 

     List<String> result = new ArrayList<String>(); 

     for(int i = 0; i < base.length; ++i) 
     { 
      for(String str: strList) 
      { 
       result.add(base[i] + str); 
      } 
     } 

     return result;  
    } 
} 

नज़र लगता है कि एक लंबी स्ट्रिंग से बराबर हैश स्ट्रिंग बहुत कठिन है, एक छोटी स्ट्रिंग (2 या 3) के बराबर हैश स्ट्रिंग को ढूंढना आसान है। नीचे समीकरण देखें। (खेद है कि मैं छवि पोस्ट नहीं कर सकता हूं मुझे नया सदस्य)

ध्यान दें कि, "एफबी" और "ईए" में एक ही हैशकोड है, और एस 1 + "एफबी" + एस 2 और एस 1 + "ईए" + एस 2 जैसे किसी भी दो तार होंगे एक ही हैशकोड। तो, आसान समाधान मौजूदा स्ट्रिंग के किसी भी 2-चार-स्ट्रिंग खोजने और एक ही hashCode

उदाहरण के लिए, हम स्ट्रिंग "HelloWorld" 2-चार-स्ट्रिंग मिलता है "के साथ एक 2-चार-स्ट्रिंग के साथ बदलें है वह ", हैशकोड (" वह ") = 'एच' * 31 + 'ई' = ('एच' * 31 + 31) + ('ई' - 31) = ('एच' + 1) * 31 + 'एफ '=' i '+' F '= हैशकोड ("iF") इसलिए इच्छा स्ट्रिंग "iFlloworld" है, हमने 1 से' एच 'बढ़ाया है, हम 2, या 3 आदि तक बढ़ सकते हैं (लेकिन गलत होगा अगर यह चार मान ओवरफ्लो)

नीचे दिया गया कोड छोटे स्तर के साथ अच्छी तरह से चलाया जाता है, यदि स्तर बड़ा होता है तो यह गलत होगा, चार मान ओवरफ्लो बनाएं, मैं f यह ix बाद में यदि आप (कोड में यह परिवर्तन 2 पहले वर्ण, लेकिन क्योंकि 2 पहले वर्ण सबसे बड़ा मूल्य के साथ calc हैं मैं 2 पिछले वर्ण के लिए कोड संपादित करेंगे) चाहते

public static String samehash(String s, int level) { 
    if (s.length() < 2) 
     return s; 
    String sub2 = s.substring(0, 2); 
    char c0 = sub2.charAt(0); 
    char c1 = sub2.charAt(1); 
    c0 = (char) (c0 + level); 
    c1 = (char) (c1 - 31 * level); 
    String newsub2 = new String(new char[] { c0, c1 }); 
    String re = newsub2 + s.substring(2); 
    return re; 
} 
+0

मैं सिर्फ सवाल संपादित करता हूं। हम सही दिशा की ओर हैं जो मुझे लगता है। धन्यवाद। – StarPinkER

+1

मुझे लगता है कि सबसे अच्छा सवाल है "एक रिवर्स हैशकोड फ़ंक्शन लिखें" – yelliver

+0

वास्तव में कोई पुरानी स्ट्रिंग करेगा, कोई हैशकोड मान करेगा। – StarPinkER

1

मैं अगर वहाँ था एक "सार्वभौमिक" सोच रहा था उपाय; जैसे कुछ निरंतर स्ट्रिंग XYZ, ऐसी है कि

s.hashCode() == (s + XYZ).hashCode() 
किसी भी स्ट्रिंग s के लिए

। ऐसी स्ट्रिंग को ढूंढना एक जटिल जटिल समीकरण को हल करना शामिल है ... जो मेरी जंगली गणितीय क्षमता से परे था। लेकिन फिर यह मेरे सामने आया कि h == 31*h + ch हमेशा true है जब h और ch शून्य दोनों हैं!

कि अंतर्दृष्टि के आधार पर, निम्नलिखित विधि अपने तर्क के रूप में एक ही hashCode के साथ एक अलग स्ट्रिंग बनाना चाहिए:

public String collider(String s) { 
     return "\0" + s; 
    } 

तो NUL पात्रों आप के लिए समस्याग्रस्त हैं, prepending किसी भी स्ट्रिंग जिसका hashCode शून्य होता है काम भी करें ... यद्यपि यदि आप शून्य का उपयोग करते हैं तो टकराव तार अधिक लंबा होगा।

+0

मुझे कोशिश करें कि \ 0 समाधान काम करेगा या नहीं। धन्यवाद। – StarPinkER