2014-04-13 39 views
46

के साथ दो मानचित्र <स्ट्रिंग, इंटीजर> विलय करना मेरे पास दो (या अधिक) Map<String, Integer> ऑब्जेक्ट्स हैं। मैं उन्हें जावा 8 स्ट्रीम एपीआई के साथ इस तरह से विलय करना चाहता हूं कि सामान्य कुंजी के मान मूल्यों का अधिकतम होना चाहिए।जावा 8 स्ट्रीम एपीआई

@Test 
public void test14() throws Exception { 
    Map<String, Integer> m1 = ImmutableMap.of("a", 2, "b", 3); 
    Map<String, Integer> m2 = ImmutableMap.of("a", 3, "c", 4); 
    List<Map<String, Integer>> list = newArrayList(m1, m2); 

    Map<String, Integer> mx = list.stream()... // TODO 

    Map<String, Integer> expected = ImmutableMap.of("a", 3, "b", 3, "c", 4); 
    assertEquals(expected, mx); 
} 

मैं इस परीक्षण विधि को हरा कैसे बना सकता हूं?

मैंने बिना किसी सफलता के collect और Collectors के साथ खेला है।

(ImmutableMap और newArrayList गूगल अमरूद से कर रहे हैं।)

उत्तर

68
@Test 
public void test14() throws Exception { 
    Map<String, Integer> m1 = ImmutableMap.of("a", 2, "b", 3); 
    Map<String, Integer> m2 = ImmutableMap.of("a", 3, "c", 4); 

    Map<String, Integer> mx = Stream.of(m1, m2) 
     .map(Map::entrySet)   // converts each map into an entry set 
     .flatMap(Collection::stream) // converts each set into an entry stream, then 
            // "concatenates" it in place of the original set 
     .collect(
      Collectors.toMap(  // collects into a map 
       Map.Entry::getKey, // where each entry is based 
       Map.Entry::getValue, // on the entries in the stream 
       Integer::max   // such that if a value already exist for 
            // a given key, the max of the old 
            // and new value is taken 
      ) 
     ) 
    ; 

    /* Use the following if you want to create the map with parallel streams 
    Map<String, Integer> mx = Stream.of(m1, m2) 
     .parallel() 
     .map(Map::entrySet)   // converts each map into an entry set 
     .flatMap(Collection::stream) // converts each set into an entry stream, then 
            // "concatenates" it in place of the original set 
     .collect(
      Collectors.toConcurrentMap(  // collects into a map 
       Map.Entry::getKey, // where each entry is based 
       Map.Entry::getValue, // on the entries in the stream 
       Integer::max   // such that if a value already exist for 
            // a given key, the max of the old 
            // and new value is taken 
      ) 
     ) 
    ; 
    */ 

    Map<String, Integer> expected = ImmutableMap.of("a", 3, "b", 3, "c", 4); 
    assertEquals(expected, mx); 
} 
+0

ग्रेट! मुझे बस एक चीज की आवश्यकता है, अधिकतम की बजाय, मुझे औसत की आवश्यकता है। मैं यह कैसे कर सकता हूं? –

+1

@FirasAlMannaa https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#average-- –

48
Map<String, Integer> mx = new HashMap<>(m1); 
m2.forEach((k, v) -> mx.merge(k, v, Integer::max)); 
12
mx = list.stream().collect(HashMap::new, 
     (a, b) -> b.forEach((k, v) -> a.merge(k, v, Integer::max)), 
     Map::putAll); 

यह किसी भी आकार सूची के लिए सामान्य स्थिति को शामिल किया गया है और किसी भी प्रकार के साथ काम करना चाहिए, बस Integer::max बाहर स्वैप और/या HashMap::new वांछित के रूप में।

आप परवाह नहीं है तो जो मूल्य मर्ज में बाहर आता है, वहाँ एक अधिक स्वच्छ समाधान है:

mx = list.stream().collect(HashMap::new, Map::putAll, Map::putAll); 

और सामान्य तरीके के रूप में:

public static <K, V> Map<K, V> mergeMaps(Stream<? extends Map<K, V>> stream) { 
    return stream.collect(HashMap::new, Map::putAll, Map::putAll); 
} 

public static <K, V, M extends Map<K, V>> M mergeMaps(Stream<? extends Map<K, V>> stream, 
     BinaryOperator<V> mergeFunction, Supplier<M> mapSupplier) { 
    return stream.collect(mapSupplier, 
      (a, b) -> b.forEach((k, v) -> a.merge(k, v, mergeFunction)), 
      Map::putAll); 
} 
1

मैं proton pack library करने के लिए अपने योगदान के लिए जोड़ा जिसमें स्ट्रीम एपीआई के लिए उपयोगिता विधियां शामिल हैं।

Map<String, Integer> mx = MapStream.ofMaps(m1, m2).mergeKeys(Integer::max).collect(); 
मूल रूप से mergeKeys

एक नया मानचित्र में कुंजी-मान जोड़ों एकत्रित करेगा (प्रदान मर्ज समारोह वैकल्पिक है, यदि आप एक Map<String, List<Integer>> अन्यथा के साथ पहुंच जाएंगे) और stream() याद: यहाँ आप कैसे प्राप्त कर सकते थे तुम क्या चाहते हो एक नया MapStream प्राप्त करने के लिए entrySet() पर। इसके परिणामस्वरूप मानचित्र प्राप्त करने के लिए collect() का उपयोग करें।

1

का उपयोग StreamEx आप कर सकते हैं:

StreamEx.of(m1, m2) 
    .flatMapToEntry(x -> x) 
    .grouping(IntCollector.max()) 
-3

यह इंजीनियरिंग खत्म हो गया है, तो आप सिर्फ कर सकते हैं:

map3 = new HashMap<>(); 
map3.putAll(map1); 
map3.putAll(map2); 
+5

यह इस शर्त की गारंटी नहीं देता है: "सामान्य कुंजी के लिए मान होना चाहिए अधिकतम मान "। – palacsint

+1

यह उस स्थिति को _address_ करने का भी प्रयास नहीं करता है। –

1

मैं किसी के लिए भी @srborlongan क्या किया का एक दृश्य प्रतिनिधित्व बना लिया है, जो रुचि हो सकती है।

enter image description here

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