2012-09-05 11 views
7

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

यह मेरा विन्यास है:कुंजी डालने पर कस्टम बराबर/हैश (गुवा कैश)

CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).recordStats(). 
    expireAfterWrite(DEFAULT_AGE, TimeUnit.DAYS).build(
    new CacheLoader<Request, Response>() { 
     @Override 
     public Response load(Request request) { 
      return request.getResponse(); 
     } 
    }); 

और ये मेरे हैश फंक्शन (मेरे कोड में कहीं और प्रयोग किया जाता) है:

public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + code; 
    result = prime * result + messageID; // <= **this one shouldn't evaluated** 
    result = prime * result + Arrays.hashCode(payload); 
    result = prime * result + (int) (timestamp^timestamp >>> 32); // <= **this one shouldn't evaluated** 
    result = prime * result + (type == null ? 0 : type.hashCode()); 
    result = prime * result + version; 
    return result; 
} 
Btw

, के अपने स्वयं के कार्यान्वयन का उपयोग कैश के इस प्रकार है हैश फ़ंक्शन (उदाहरण के लिए, आत्मनिरीक्षण के माध्यम से) या क्या यह डिफ़ॉल्ट का उपयोग कर रहा है?

** संपादित करें: **
के रूप में प्रतिक्रिया में कहा, सबसे अच्छा तरीका यह परिणाम प्राप्त करने के लिए एक आवरण वर्ग है।
मेरे समाधान:

/** 
* Nested class to store a request as a key in the cache. It is needed to 
* normalize the variable fields of the normal requests. 
*/ 
private static final class CachedRequest extends Request { 

    private static CachedRequest fromRequest(Request request) { 
     // set only the fields that cannot change between two same requests 
     // ... 
    } 

    @Override 
    public int hashCode() { 
     HashFunction hashFunction = Hashing.md5(); 
     HashCode hashCode; 
     // ... 
     return hashCode.asInt(); 
    } 

    @Override 
    public boolean equals(Object obj) { 
      // coherent with hashCode() 
      // ... 
    } 
} 
+0

मैं कल्पना नहीं कर सकता कि यह एक बहुत ही उपयोगी उपयोगिता होगी यदि यह अपने स्वयं के हैश कार्यान्वयन का उपयोग करता है। – jtahlborn

+0

भी, क्या आप आगे बता सकते हैं कि "मैं अपने हैश() फ़ंक्शन को संशोधित नहीं कर सकता क्योंकि यह पहले से ही" वास्तविक "वस्तुओं को बराबर पहचानने के लिए उपयोग किया जाता है।" – jtahlborn

+0

असल में मैं इस सुविधा को जोड़ने के लिए नहीं कह रहा हूं, लेकिन अगर कोई जानता है कि इस स्थिति से कैसे निपटें। – Hamal000

उत्तर

13

आप बस CachedRequest वस्तुओं, जहां CachedRequesthashCode() और equals() वांछित क्षेत्रों के आधार पर लागू होता है, और लिपटे Request के लिए पहुँच प्रदान में अपने Request वस्तुओं लपेट सकता है।

1

आप हैश समारोह को संशोधित नहीं कर सकते हैं (मैं अभी भी क्यों समझ में नहीं आता है), तो आप एक "आवरण" कुंजी का उपयोग करने के लिए कैश जैसे की जरूरत है,:

public class RequestKey { 
    private final Request _req; 

    public int hashCode() { 
    // use appropriate Request fields here 
    } 

    public boolean equals(Object o) { 
    return ((this == o) || ((o != null) && (getClass() == o.getClass()) && _req.equals(((RequestKey)o)._req))); 
    } 
} 
+0

के साथ संगत-अनुरूप-बराबर मैं हैश को संशोधित नहीं कर सकता क्योंकि यह विरासत कोड है और हैश पहले से कहीं और उपयोग किया जा रहा है। – Hamal000

+0

@ हमल000 - मैं इसे समझता हूं। हालांकि, हैशकोड से फ़ील्ड को हटाने से इसकी उपयोगिता कहीं और कम नहीं होनी चाहिए (उदाहरण के लिए, जब तक आप लगातार इन हैशकोड को संग्रहीत नहीं कर रहे हैं, उदाहरण के लिए, डेटाबेस) – jtahlborn

+0

ठीक है, एक फ़ील्ड को हटाने का मतलब उस जगह को कम करना है जहां हैश फ़ंक्शन ऑब्जेक्ट्स मैप कर रहा है, लेकिन यह समस्या नहीं है ... दुर्भाग्य से हैश, मेरे मामले में, क्लाइंट पक्ष पर कहीं भी आईडी के रूप में उपयोग किया जाता है (इस फ़ंक्शन के साथ)। – Hamal000

1

मैं बहुत हूँ यकीन है, गुवा के साथ यह संभव नहीं है। कस्टम समतुल्यता का उपयोग करने के लिए कुछ वैध मामले हैं, लेकिन वे कहते हैं कि CacheBuilder और MapMaker द्वारा उन्हें संभालने के लिए बहुत दुर्लभ हैं। यहां तक ​​कि com.google.common.base.Equivalence भी है, लेकिन यह केवल आंतरिक रूप से उपयोग किया जाता है (here और here देखें)।

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

केवल मामला है जब कुछ डिफ़ॉल्ट equals/hashCode से अलग इस्तेमाल किया जाता है (softKeys नहीं मौजूद है) weakKeys के साथ है, और फिर इसे ==/System.identityHashCode कॉम्बो है। किसी भी मामले में आप समानता को स्वतंत्र रूप से चुन सकते हैं।

+0

+1 कमजोर के लिए +1 – Hamal000

+1

'समतुल्यता' सार्वजनिक है: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Equivalence.html – fry

+0

@fry: वास्तव में यह है, लेकिन केवल एक सार्वजनिक उपयोग है ('Maps.difference' में)। – maaartinus

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