2016-03-24 11 views
7

मैं जावा 8 स्ट्रीम के साथ दो मानचित्र मर्ज करना चाहते हैं:नक्शा <स्ट्रिंग, सूची <String> जावा मर्ज 8 स्ट्रीम

Map<String, List<String>> mapGlobal = new HashMap<String, List<String>>(); 
Map<String, List<String>> mapAdded = new HashMap<String, List<String>>(); 

मैं इस कार्यान्वयन का उपयोग करने का प्रयास करें:

mapGlobal = Stream.of(mapGlobal, mapAdded) 
       .flatMap(m -> m.entrySet().stream()) 
       .collect(Collectors.groupingBy(Map.Entry::getKey, 
         Collectors.mapping(Map.Entry::getValue,   
              Collectors.toList()) 
       )); 

हालांकि, इस कार्यान्वयन

Map<String, List<Object>>

: केवल की तरह एक परिणाम बनाने यदि mapGlobal में एक कुंजी निहित नहीं है, तो इसे स्ट्रिंग की इसी सूची के साथ एक नई कुंजी के रूप में जोड़ा जाएगा। यदि कुंजी mapGlobal और mapAdded में डुप्लिकेट की गई है, तो मानों की दोनों सूची मर्ज हो जाएगी: A = {1, 3, 5, 7} और B = {1, 2, 4, 6} फिर A ∪ B = {1, 2, 3, 4, 5, 6, 7}

उत्तर

7

आप mapAdded में सभी प्रविष्टियों को फिर से चलाकर और mapGlobal में विलय करके ऐसा कर सकते हैं।

forEach(action) जहां कार्रवाई कुंजी और प्रत्येक प्रविष्टि के मान की खपत को फोन करके mapAdded की प्रविष्टियों पर निम्नलिखित दोहराता। प्रत्येक प्रविष्टि के लिए, हम merge(key, value, remappingFunction) पर mapGlobal पर कॉल करते हैं: यह या तो कुंजी k के अंतर्गत प्रविष्टि बनायेगा और v मानता है यदि कुंजी मौजूद नहीं है या यदि वे पहले से मौजूद हैं तो यह दिए गए रीमेपिंग फ़ंक्शन का आह्वान करेगा। इस समारोह 2 सूचियों विलय करने के लिए, जो इस मामले में, पहले एक TreeSet लिए जोड़ रहे हैं दोनों अद्वितीय सुनिश्चित करने के लिए और तत्वों छाँटे गए और एक सूची में वापस परिवर्तित लेता है:

mapAdded.forEach((k, v) -> mapGlobal.merge(k, v, (v1, v2) -> { 
    Set<String> set = new TreeSet<>(v1); 
    set.addAll(v2); 
    return new ArrayList<>(set); 
})); 

आपको लगता है कि चलाने के लिए संभावित रूप से समानांतर में चाहते हैं , आप entrySet() प्राप्त करके और parallelStream() पर कॉल करके स्ट्रीम पाइपलाइन बना सकते हैं। लेकिन फिर, आपको mapGlobal, ConcurrentHashMap की तरह, एक मानचित्र का उपयोग करना सुनिश्चित करना होगा जो mapGlobal के लिए concurrency का समर्थन करता है।

ConcurrentMap<String, List<String>> mapGlobal = new ConcurrentHashMap<>(); 
// ... 
mapAdded.entrySet().parallelStream().forEach(e -> mapGlobal.merge(e.getKey(), e.getValue(), (v1, v2) -> { 
    Set<String> set = new TreeSet<>(v1); 
    set.addAll(v2); 
    return new ArrayList<>(set); 
})); 
+0

यह कार्यान्वयन स्ट्रीम संग्रह में सुधारों का उपयोग नहीं करेगा। दोनों नक्शे विशाल हो सकते हैं तो मैं समानांतरस्ट्रीम() जैसे कुछ का उपयोग करना चाहता हूं। क्या यह संभव है। – ypriverol

+2

@ypriverol हाँ आप कर सकते हैं, मैं इसके साथ संपादित किया। – Tunaki

+2

जब तक 'mapGlobal' एक' ConcurrentMap' नहीं है, इसे समांतर धारा के अंदर से म्यूट करना सुरक्षित नहीं है। – Misha

1

foreach के दौरान नक्शा ArrayList के मूल्य के साथ नक्शे को मर्ज का उपयोग करते हुए मानचित्र जिसके परिणामस्वरूप में संयुक्त।

public Map<String, ArrayList<String>> merge(Map<String, ArrayList<String>> map1, Map<String, ArrayList<String>> map2) { 
    Map<String, ArrayList<String>> map = new HashMap<>(); 
    map.putAll(map1); 

    map2.forEach((key , value) -> { 
     //Get the value for key in map. 
     ArrayList<String> list = map.get(key); 
     if (list == null) { 
      map.put(key,value); 
     } 
     else { 
      //Merge two list together 
      ArrayList<String> mergedValue = new ArrayList<>(value); 
      mergedValue.addAll(list); 
      map.put(key , mergedValue); 
     } 
    }); 
    return map; 
} 
1

मूल कार्यान्वयन Map<String, List<Object>>, लेकिन Map<String, List<List<String>>> की तरह परिणाम नहीं बनाता है। Map<String, List<String>> बनाने के लिए आपको अतिरिक्त स्ट्रीम पाइपलाइन की आवश्यकता है।

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