2012-05-14 11 views
8

क्या होगा सबसे तेज और अधिक मजबूत की तरहकई जावा स्ट्रिंग से एक हैश बनाना वस्तुओं

public abstract String hash(String[] values); 

एक विधि को लागू करने के लिए जिस तरह से (विशिष्टता के संदर्भ में) values[] सरणी 100 से 1000 के सदस्यों, एक से प्रत्येक है जो कुछ दर्जन वर्णों के साथ, और विधि को प्रत्येक बार values[] सरणी पर लगभग 10,000 गुना/सेकंड चलाने की आवश्यकता होती है।

StringBuilder बफर का उपयोग करके एक लंबी स्ट्रिंग का निर्माण करना चाहिए और फिर बफर सामग्री पर एक हैश विधि लागू की जानी चाहिए, या values[] से प्रत्येक स्ट्रिंग के लिए हैश विधि का आह्वान करना बेहतर है?

स्पष्ट रूप से टकराव से बचने के लिए कम से कम 64 बिट्स (उदाहरण के लिए, एमडी 5) की हैश की आवश्यकता है, लेकिन क्या एक ही गुणवत्ता पर कुछ भी आसान और तेज़ किया जा सकता है?

उदाहरण के लिए

,

के बारे में
public String hash(String[] values) 
{ 
    long result = 0; 

    for (String v:values) 
    { 
     result += v.hashCode(); 
    } 

    return String.valueOf(result); 
} 
+1

वह दृष्टिकोण उचित दिखता है।आप किसी क्षेत्र में हैश मान को स्टोर करना चाहते हैं, इसलिए जब भी आप इसे स्ट्रिंग [] में बदलते हैं, तब तक आपको हर बार इसे फिर से गणना करने की आवश्यकता नहीं होती है। –

+0

निश्चित रूप से, लेकिन प्रश्न में आवेदन में मूल्य [] सरणी हर समय बदल जाती है। :-) – PNS

उत्तर

9

निश्चित रूप से अपने linearity गुणों के कारण सादा इसके अलावा का उपयोग नहीं करते क्या हैं, लेकिन आप बहुत अच्छा फैलाव को प्राप्त करने के बस थोड़ा सा अपने कोड को संशोधित कर सकते हैं।

public String hash(String[] values) { 
    long result = 17; 
    for (String v:values) result = 37*result + v.hashCode(); 
    return String.valueOf(result); 
} 
+0

क्या 17 पर्याप्त है, या एक लंबे प्रधान की आवश्यकता होगी? और लाखों आक्रमणों में टकराव के बारे में क्या? – PNS

+0

टकराव अपरिहार्य हैं हालांकि आप इसे चालू करते हैं। यदि यह ऐसी चिंता है, तो आपको कुछ मजबूत और 64 बिट्स के साथ उपयोग करना चाहिए। –

1

पहला, हैश कोड आम तौर पर संख्यात्मक है, उदा। int। इसके अलावा हैश फ़ंक्शन का आपका संस्करण int बना देता है और उसके बाद स्ट्रिंग का प्रतिनिधित्व करता है कि आईएमएचओ का कोई अर्थ नहीं है।

मैं निम्नलिखित के रूप में अपने हैश विधि में सुधार चाहते हैं:

public int hash(String[] values) { 
    long result = 0; 
    for (String v:values) { 
     result = result * 31 + v.hashCode(); 
    } 
    return result; 
} 

वर्ग java.lang.String

+0

मैं सहमत हूं, लेकिन वापसी का प्रकार एक आवेदन औपचारिकता है। इसके अलावा, आपका सुझाव मार्को के समान है। क्या लाखों आक्रमणों में टकराव के संबंध में यह ठीक रहेगा? – PNS

+0

@MarkoTopolnik क्यों एक समस्या है? – augurar

2

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

hashCode के आंतरिक() इस तरह दिखेगा:।

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

इतना जोड़ने संख्याओं को एक साथ करने के लिए सरणी में सभी स्ट्रिंग्स का अंतिम अक्षर का कारण होगा बस जोड़ दिया है, जो अनियमितता को कम नहीं करता है (यह एक हैश समारोह के लिए पर्याप्त पहले से ही खराब है)।

आप वास्तविक pseudorandomness चाहते हैं, FNV हैश एल्गोरिथ्म पर एक नज़र डालें। यह वहाँ बाहर सबसे तेजी से हैश एल्गोरिथ्म है जिसे विशेष रूप से हैश मैप्स में उपयोग के लिए डिज़ाइन किया गया है।

यह इस प्रकार है:

long hash = 0xCBF29CE484222325L; 
    for(String s : strings) 
    { 
     hash ^= s.hashCode(); 
     hash *= 0x100000001B3L; 
    } 

^यह FNV के वास्तविक क्रियान्वयन के रूप में यह बाइट्स के बजाय इनपुट के रूप में ints लेता नहीं है, लेकिन मैं इसे तरह ही काम करता है।

+0

हमम ... क्या आप वाकई यहां सुझाए गए सरल, सरल दृष्टिकोण से तेज़ हैं? यादृच्छिकता शायद इसके दिखने से बेहतर है। – PNS

+0

मैंने कभी दावा नहीं किया कि यह किसी और चीज़ से तेज़ है। वास्तव में, गति अन्य उत्तरों के समान है। (लगता है कि जोड़ और xor गति के मामले में बराबर हैं) –

+0

"वास्तविक यादृच्छिकता" - यहां पाए गए कुछ भी नहीं। – Raphael

3

यह 64 बिट हैश प्रदान नहीं करता है, लेकिन सवाल का शीर्षक यह संभवतः उल्लेखनीय है कि जावा 1.7 के बाद java.util.Objects#hash(Object...) है।

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