2012-04-27 10 views
15

मैं एक साधारण HashMap आधारित कैश कि इस प्रकार काम करता है लिख रहा हूँ:जावा - विस्तार HashMap - वस्तु बनाम जेनरिक व्यवहार

  1. तो अनुरोध किया keyकैश में है, इसका value लौट आते हैं।
  2. तो अनुरोध किया key वहाँ नहीं है, एक विधि है कि पर key आधारित value पैदा करता है चलाने के लिए, दोनों की दुकान, value लौट आते हैं।

कोड:

import java.util.HashMap; 

abstract class Cache<K, V> extends HashMap<K, V> { 
    @Override 
    public V get(Object key) { 
     if (containsKey(key)) { 
      return super.get(key); 
     } else { 
      V val = getData(key); 
      put((K)key, val); // this is the line I'm discussing below 
      return val; 
     } 
    } 

    public abstract V getData(Object key); 
} 

यह बहुत सीधा है और अच्छी तरह से काम करता है। हालांकि, मैं से नफरत get() के लिए सूर्य के निर्णय Object को अपने तर्क के रूप में K से नफरत करता है। मैंने यह जानने के लिए पर्याप्त पढ़ा है कि इसके पीछे कुछ तर्क है (जिसके साथ मैं सहमत नहीं हूं, लेकिन यह एक और कहानी है)।

मेरी समस्या टिप्पणी लाइन में है, क्योंकि ऐसा लगता है कि में अनचेक होने के लिए है। टाइप एरर के कारण, कोई तरीका नहीं है कि मैं जांच कर सकता हूं कि keyK प्रकार है (जो उचित put() कार्यक्षमता के लिए आवश्यक है) और विधि, इसलिए त्रुटि प्रवण है।

एक समाधान से स्विच करने के लिए होगा "एक" के लिए HashMap संबंध जो बहुत अच्छे और साफ है "एक" है, लेकिन फिर CacheMap जो कई कारणों से अच्छा होगा लागू नहीं कर सकते। कोड:

import java.util.HashMap; 
import java.util.Map; 

abstract class Cache<K, V> { 
    private final Map<K, V> map = new HashMap<K, V>(); 

    public V get(K key) { 
     if (map.containsKey(key)) { 
      return map.get(key); 
     } else { 
      V val = getData(key); 
      map.put(key, val); 
      return val; 
     } 
    } 

    public abstract V getData(K key); 
} 

किसी को भी, किसी भी अन्य (यहां तक ​​कि hackish) समाधान के साथ आ सकते हैं, ताकि मैं Cache बनाये रख सकता है एक Map होने के लिए और अभी भी get(Object key) और put(K key, V val) के मामले में सुरक्षित प्रकार हो सकता है?

एकमात्र चीज जिसे मैं सोच सकता हूं, i.e. getValue(Key k) नामक एक और विधि बनाना है जो get(Object key) पर प्रतिनिधि होगा, लेकिन फिर मैं किसी को सामान्य की बजाय नई विधि का उपयोग करने के लिए मजबूर नहीं कर सकता।

+1

आप 'getA' या' myget' को लागू कर सकते हैं आप मानचित्र के व्यवहार को नहीं बदल सकते हैं।प्राप्त करें() क्योंकि आप कोड को मजबूर नहीं कर सकते हैं जो आपकी कक्षा के बजाय इंटरफ़ेस का उपयोग सीधे पुन: संकलित करने के लिए करता है। –

उत्तर

15

नहीं। आपको "हैस-ए" संबंध में स्विच करने का सही समाधान मिला है। (स्पष्ट रूप से, get विधि होने पर एक नया मान गणना करें यदि कोई पहले से मौजूद नहीं है, तो आश्चर्यजनक है, Map अनुबंध का उल्लंघन करता है, और कई अन्य तरीकों के लिए बेहद अजीब व्यवहार का कारण बन सकता है। यह एक बड़ा हिस्सा था कि क्यों गुवा चले गए MapMaker से, जिसने लगभग इस सटीक व्यवहार की पेशकश की - क्योंकि यह केवल riddled मुद्दों के साथ था।)

यह कहा गया, उदाहरण के लिए गुवा का Cache क्या यह Map<K, V> asMap() देखें, जो एक चीज है जो आप कर सकते हैं। इससे आपको टाइप सुरक्षा पर समझौता किए बिना Map के अधिकांश फायदे मिलते हैं।

+0

ऐसा लगता है कि 'मैपमेकर' वास्तव में मैंने जो किया है :)। मैं अजीब व्यवहार के आंशिक रूप से अवगत हूं। विधि 'वी गेटडाटा (के कुंजी)' 'सार 'है और इसलिए इसका उद्देश्य केवल कैश इंस्टेंटेशन पर निर्दिष्ट (कार्यान्वित) होना है। मैंने वर्ग को 'अंतिम सार' बनाने की भी कोशिश की (भले ही मुझे 100% पता था कि यह काम नहीं करेगा) या सिर्फ 'अंतिम' (गुमनाम आंतरिक वर्ग द्वारा अतिरंजित विधि के साथ - निश्चित रूप से, काम नहीं करता है) यह सुनिश्चित करने के लिए कि कोई भी इस व्यावसायिक खतरे के साथ इस खतरनाक टुकड़े को उपclass करने का प्रयास नहीं करेगा। वैसे भी, बहुत धन्यवाद, 'as-a "संबंध' asMap() 'के साथ _view_ दे रहा है। –

+0

वैसे, मुझे विश्वास नहीं है कि मैं अमरूद के कैश से चूक गया था। मैं अब इसका उपयोग नहीं करूंगा (जब मेरा अपना कार्यान्वयन होता है) गर्व से, लेकिन अगर मुझे कल पता था ... :) –

+5

आपको ... कोवा के 'कैश' का उपयोग करने पर विचार करना चाहिए। इसका उपयोग Google उत्पादन में किया जाता है, इसलिए इसका अत्यधिक परीक्षण और अनुकूलित किया गया है, और यह आसान सुविधाओं के [बहुत] (http://code.google.com/p/guava-libraries/wiki/CachesExplained) मिला है। –

0

निश्चित रूप से एक रिश्ता एक सही कार्यान्वयन है। मूल्य उत्पन्न होने के तरीके के व्यापार तर्क को कैश वर्ग से हटा दिया जाना चाहिए।

+0

यह इसके बारे में मजेदार हिस्सा है - इसमें कोई तर्क नहीं है! विधि 'सार' है और इसलिए कैश तत्कालता पर केवल निर्दिष्ट (लागू, ओवर्रिडेन - जो भी आपको सबसे ज्यादा पसंद है) होना चाहिए। मैंने वर्ग को 'अंतिम सार' बनाने की भी कोशिश की (भले ही मुझे 100% पता था कि यह काम नहीं करेगा) या सिर्फ 'अंतिम' (गुमनाम आंतरिक वर्ग द्वारा अतिरंजित विधि के साथ - निश्चित रूप से, काम नहीं करता है) यह सुनिश्चित करने के लिए कि कोई भी इस व्यावसायिक खतरे के साथ इस खतरनाक टुकड़े को उपclass करने का प्रयास नहीं करेगा। –