2011-05-09 14 views
7

द्वारा समवर्ती मानचित्र प्रविष्टियों को क्रमबद्ध करें Map का थ्रेड-सुरक्षित कार्यान्वयन करने का कोई तरीका है जो इसकी प्रविष्टियों को मूल्य द्वारा क्रमबद्ध करता है? मैं जानता हूँ कि मैं एक धागा सुरक्षित इसमूल्य

ConcurrentMap<String, Double> rankings = new ConcurrentHashMap<String, Double>(); 

तरह Map बना सकते हैं और मैं तो एक उपयोगिता विधि करने के लिए इसे इस तरह पारित करके प्रविष्टियों मूल्य के अनुसार क्रमबद्ध प्राप्त कर सकते हैं:

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { 
    List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet()); 
    Collections.sort(list, new Comparator<Map.Entry<K, V>>() { 
     @Override 
     public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) { 
      return (o1.getValue()).compareTo(o2.getValue()); 
     } 
    }); 

    Map<K, V> result = new LinkedHashMap<K, V>(); 
    for (Map.Entry<K, V> entry : list) { 
     result.put(entry.getKey(), entry.getValue()); 
    } 
    return result; 
} 

लेकिन मैं क्या ' मैं देख रहा हूं कि एक थ्रेड-सुरक्षित Map है कि मान द्वारा क्रमबद्ध प्रविष्टियों को रखता है, ताकि मुझे मान द्वारा क्रमबद्ध प्रविष्टियों को रखने के लिए उपरोक्त के रूप में उपरोक्त विधि को कॉल करने की आवश्यकता न हो। मुझे लगता है कि मैं एक कार्यान्वयन की तलाश में हूं जो ConcurrentHashMap और LinkedHashMap के व्यवहार को जोड़ती है, लेकिन अभी तक कोई नहीं मिला है।

ConcurrentSkipListMap लगभग जो भी मैं चाहता हूं उसे प्रदान करता है, लेकिन यह केवल महत्वपूर्ण मूल्य द्वारा क्रमबद्ध करने का समर्थन करता है।

+0

आपके उपयोग-मामले में, क्या आप समस्या को * अद्वितीय * मानों तक सीमित कर सकते हैं, या क्या आपको कभी-कभी डुप्लिकेट मान मिलते हैं? यदि आपके पास डुप्लिकेट मान हैं, तो क्या आपके पास और अधिक क्रमबद्ध बाधाएं हैं? –

+0

इसके अलावा, कृपया स्पष्ट करें - क्या आप चाहते थे * क्रमबद्ध * या * आदेश दिया *? एक LinkedHashMap आपको आदेश देता है, लेकिन क्रमबद्ध नहीं करता है। –

+0

उम ..... क्रमबद्ध और आदेशित के बीच क्या अंतर है? –

उत्तर

2

इसके लिए एक समग्र डेटा संरचना बनाने पर विचार करें। उच्च स्तर पर, निम्न कार्य करें।

सबसे पहले, कुंजी-मूल्य जोड़े रखने के लिए Map.Entry लागू करें। जोड़ी का ऑर्डरिंग मूल्य से पहले होगा, और उसके बाद कुंजी।

private static class InternalEntry<K extends Comparable<K>, 
            V extends Comparable<V>> 
     implements Comparable<InternalEntry<K, V>>, 
        Map.Entry<K, V> { 
    private final K _key; 
    private final V _val; 

    InternalEntry(K key, V val) { 
     _key = key; 
     _val = val; 
    } 

    public K getKey() { 
     return _key; 
    } 

    public V getValue() { 
     return _val; 
    } 

    public V setValue(V value) { 
     throw new UnsupportedOperationException(); 
    } 

    public int compareTo(InternalEntry<K, V> o) { 
     int first = _val.compareTo(o._val); 
     if (first != 0) { 
      return first; 
     } 
     return _key.compareTo(o._key); 
    } 
} 

पूरे प्रविष्टि एक आदेश दिया नक्शा कुंजी रूप में इस्तेमाल किया जा सकता है।

लेकिन यह नक्शा कुंजी द्वारा मूल्य के कुशल लुकअप का समर्थन नहीं करता है। इसे प्राप्त करने के लिए, एक और मानचित्र प्रस्तुत करें, जो प्रविष्टियों के लिए कुंजी मानचित्र करता है।

समग्र संरचना इस तरह दिखता है:

class OrderedByValue<K extends Comparable<K>, V extends Comparable<V>> { 
    private final Map<InternalEntry<K, V>, Boolean> _ordering = 
     new TreeMap<InternalEntry<K, V>, Boolean>(); 

    private final Map<K, InternalEntry<K, V>> _lookup = 
     new HashMap<K, InternalEntry<K, V>>(); 

    public V put(K key, V val) { 
     InternalEntry<K, V> entry = new InternalEntry<K, V>(key, val); 
     InternalEntry<K, V> old = _lookup.put(key, entry); 
     if (old == null) { 
      _ordering.put(entry, Boolean.TRUE); 
      return null; 
     } 
     _ordering.remove(old); 
     _ordering.put(entry, Boolean.TRUE); 
     return old.getValue(); 
    } 

    @SuppressWarnings({"unchecked"}) 
    public Iterable<Map.Entry<K, V>> entrySet() { 
     Iterable entries = Collections.unmodifiableSet(_ordering.keySet()); 
     return (Iterable<Map.Entry<K, V>>) entries; 
    } 
} 

ध्यान दें कि मैं सभी आवश्यक कोड की आपूर्ति नहीं की है एक पूर्ण नक्शा लागू करने के लिए - यदि आप अन्य तरीकों के साथ मदद की जरूरत है मुझे पता है।

यदि आपको शून्य कुंजी/मानों को समर्थित करने की आवश्यकता है तो आपको InternalEntry की तुलना कार्यान्वयन में कुछ विशेष केस कोड भी करने की आवश्यकता है।

+0

@ डेव, मैंने ट्रीमैप, लिंक्ड हैशैप को अपने समवर्ती भाइयों के साथ स्विच करने के लिए इसे छोड़ दिया है। –