2011-11-17 10 views
8

में नेस्टेड मानचित्र या संयुक्त कुंजी मुझे जावा में कैश बनाने के लिए एक मानचित्र की आवश्यकता है, जिसमें मेरे पास दो स्ट्रिंग कुंजी हैं। मेरा सवाल है कि नेस्टेड मैप्स (प्रत्येक कुंजी के लिए एक) बनाना या दो स्ट्रिंग्स के साथ बनाई गई कुछ प्रकार की कस्टम कुंजी बनाना बेहतर है?जावा

कैश पर डेटा तक पहुंच हमेशा दो चाबियों तक पहुंच जाएगी और मुझे उस दो कुंजी में से किसी एक समूह की आवश्यकता नहीं है।

फिर यदि बेहतर है तो स्ट्रिंग कुंजी को बेहतर तरीके से संयोजित करें, यह बेहतर है?

  • कस्टम getHash विधि के साथ कस्टम क्लास। लेकिन फिर समस्या यह है कि हैश फ़ंक्शन लागू करता है?
  • बस दो स्ट्रिंग्स को एकसाथ संयोजित करें। उदाहरण के लिए:

    cache.put (कुंजी 1 + कुंजी 2, मूल्य)

उत्तर

10

आप या तो नेस्टेड मानचित्र बना सकते हैं या hashCode() को परिभाषित करने वाले कस्टम क्लास का उपयोग कर सकते हैं।

यह आमतौर पर एक अच्छा विचार कुंजी को श्रेणीबद्ध करने के लिए नहीं है, आप, टक्कर के साथ खत्म हो सकता है कुंजी 1 और 22 और चाबी 12 और 2 साथ मामले में। वे एक ही मूल्य 122 पर नक्शा करेंगे।

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

public class MyCache { 

    private Map<MyKey, Object> cache = new HashMap<MyKey, Object>(); 

    public Object getObject(Object key1, Object key2){ 
     return cache.get(new MyKey(key1, key2)); 
    } 
    public void putObject(Object key1, Object key2, Object value){ 
     cache.put(new MyKey(key1, key2), value); 
    } 
} 

याद रखें अपनी कस्टम कुंजी कक्षा में equals() और hashCode() परिभाषित करने के लिए (यदि आवश्यक हो तो शून्यता के लिए चेक जोड़ें)।

public int hashCode() { 
    int result = 17; 
    result = 37 * result + keyA.hashCode(); 
    result = 37 * result + keyB.hashCode(); 
    return result; 
} 

public boolean equals(Object another) { 
    return another.keyA.equals(keyA) && another.keyB.equals(keyB); 
} 
2

संयुक्त कुंजियों का उपयोग मेरे लिए अधिक तार्किक, और उपयोग करने के लिए (आप नेस्टेड मानचित्र होने के बारे में चिंता करने की ज़रूरत नहीं है आसान लगता है instancied)।

कुंजी के संयोजन के बारे में, एक कस्टम क्लास का उपयोग करें। यह अर्थपूर्ण रूप से अधिक समझ में आता है, और यदि आपके समान स्ट्रिंग हैं तो कॉलिजन को रोकता है। यदि आपके पास ["ab", "c"] और कुंजी ["a", "bc"] है तो ऐसा एक संयोजन दिखाई दे सकता है।

याद रखें कि जब आप अपनी कस्टम कक्षा लिखते हैं, तो आपको equals और hashCode विधियों को सही तरीके से लिखना होगा, या आपका कैश काम नहीं कर सकता है (और प्रदर्शन समस्याओं को भी भुगत सकता है)।

3

नेस्टेड मैप्स (प्रत्येक कुंजी के लिए एक) बनाना बेहतर है या दो स्ट्रिंग्स के साथ बनाई गई कुछ प्रकार की कस्टम कुंजी बनाना बेहतर है?

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

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

0

मुझे लगता है कि नेस्टेड मानचित्रों का उपयोग कम इष्टतम तरीका है। मैं अपने दूसरे विचार के साथ सहमत हूँ - ओवरराइड hashCode

public int hashCode(){ 
    return str1+str2.hashCode(); 
} 


और equals

public boolean equals(Object o){ 
    //compare both keys here 
} 

इसके अलावा के साथ एक कस्टम वर्ग को लागू मत भूलना संग्रहीत वस्तु की कक्षा में एक ही तरीके का ओवरराइड करने के लिए।

फिर, [ "ab", "सी"] के मामले में आप एक ही हैश कोड होगा, लेकिन अलग बराबरी परिणाम

12

आप अमरूद के Table कक्षाएं विचार कर सकते हैं। वे प्रति मान दो कुंजी के साथ Map लागू करते हैं। यह आपकी आवश्यकताओं के आधार पर एक समग्र कुंजी की तुलना में अधिक पठनीय समाधान प्रदान कर सकता है।

Table<String, String, MyValue> 
+0

बहुत बहुत धन्यवाद, यह वही था जो मैं ढूंढ रहा था! केवल गुवा के मल्टीमैप्स पर ठोकर खाई, जो मेरे लिए सुविधाजनक नहीं थे। ;) –

+0

@FlorianPilz एनपी, चीयर्स –

+0

अमरूद के हैशबेसेडटेबल के बारे में एक नोट, यह एक नेस्टेड मानचित्र दृष्टिकोण का उपयोग करता है। – PhoneixS

1

मैं एक कैशिंग प्रणाली कुंजी पीढ़ी के लिए विधि paramaters का उपयोग करने के लिए आवश्यक है कि के साथ एक समान समस्या थी। मैंने ज़वी के जवाब के समान एक रैपर वर्ग लिखना समाप्त कर दिया।

public final class ArrayWrapper 
{ 
    private final Object[] array; 

    public ArrayWrapper(final Object... array) 
    { 
     this.array = array; 
    } 

    public Object[] getArray() 
    { 
     return this.array; 
    } 

    public boolean equals(Object o) 
    { 
     if (o == null) return false; 
     if (o == this) return true; 
     if (o instanceof ArrayWrapper) 
     { 
      return Arrays.equals(this.array, ((ArrayWrapper)o).array); 
     } 
     return false; 
    } 

    private int hashCode(Object o) 
    { 
     if (o == null) return 0; 
     return o.hashCode(); 
    } 

    public int hashCode() 
    { 
     int sum = 17; 
     if (this.array != null) for(int i = 0;i<this.array.length;i++) 
     { 
      sum = 37 * sum + this.hashCode(this.array[i]); 
     } 
     return sum; 
    } 

    public String toString() 
    { 
     if (this.array != null) 
     { 
      return "Wrapper " + Arrays.toString(array); 
     } 
     else return "Wrapper []"; 
    } 
} 

नया रैपर बनाएं और इसे मानचित्र की कुंजी के रूप में उपयोग करें। आप एक कस्टम मैप भी लिख सकते हैं और इसे मैन्युअल रूप से लपेटने के बजाय सरणी (vararg पाने के लिए) को स्वीकार करने के लिए प्राप्त करें और विधियों को ओवरलोड करें।