আমি একই ধরণের দুটি হ্যাশম্যাপ অবজেক্টকে কীভাবে একত্রিত করতে পারি?


241

আমার HashMapমতো দুটি সংজ্ঞা দেওয়া হয়েছে:

HashMap<String, Integer> map1 = new HashMap<String, Integer>();
HashMap<String, Integer> map2 = new HashMap<String, Integer>();

আমার একটি তৃতীয় HashMapবস্তুও রয়েছে:

HashMap<String, Integer> map3;

আমি কিভাবে মার্জ করতে পারবেন map1এবং map2মধ্যে একসঙ্গে map3?


16
উভয় মানচিত্রে একটি কী উপস্থিত থাকলে আপনি কী হতে চান তা আপনি জানাননি।
মাইকেল শ্যাপার

উত্তর:


344
map3 = new HashMap<>();

map3.putAll(map1);
map3.putAll(map2);

1
আপনাকে ধন্যবাদ, আমি মানচিত্রে একটি লুপের জন্য মার্জ করছি যা কোনও পদ্ধতি ব্যবহার করে কোনও মানচিত্র ফেরত দেয় এবং এটিকে অন্য মানচিত্রে একীভূত করতে হবে এবং একই পদ্ধতিতে আগিয়ান প্রয়োগ করতে হবে। এর জন্য, আমি পুটএল পদ্ধতিতে নাল পয়েন্টার ব্যতিক্রম পাই। এটি ট্রাই / ক্যাচ ব্লক ব্যবহারে সহায়তা করে না। আমার কি করা উচিৎ? আমি শর্ত প্রযোজ্য যে যদি আকার == ণ তারপর putAll প্রযোজ্য হবে না অন্যথায় এটা প্রযোজ্য am ইত্যাদি ....
Mavin

1
আপনি যদি এনপিই পান তবে স্পষ্টতই আপনি আপনার কোনও একটি জিনিস সঠিকভাবে শুরু করেন নি। আপনি কি ক্যাচ ব্লকে স্ট্যাকট্রেস মুদ্রণ করেন? সুতরাং আপনি জানেন কোথায় সমস্যা দেখা দেয়। তবে আপনি যদি স্ট্যাক ট্রেস সহ সম্পূর্ণ এবং সঠিক কোড পোস্ট না করেন তবে আপনার নিজের এটি নিজেই ট্র্যাক করতে হবে।
a_horse_with_no_name

95
মনে রাখবেন যে, এই সমাধানের সাহায্যে, উভয় মানচিত্রে একটি কী উপস্থিত থাকলে, মানচিত্র 2 এর মান সংরক্ষণ করা হবে এবং মানচিত্র 1 এর মান হারাবে।
মাইকেল শ্যাপার

5
@ মিশেলশেপার: আপনি আর কী আশা করবেন? Map
একটিতে

42
অপার কী প্রত্যাশা করে তা আমি জানি না। হতে পারে তিনি মানচিত্রের 1 মানগুলির অগ্রাধিকার, বা একটি ব্যতিক্রম ছুঁড়ে ফেলার বা প্রত্যাখ্যান পূর্ণসংখ্যার উপর কিছু 'মার্জিং' অপারেশন করার জন্য প্রত্যাশা করছেন। বা হতে পারে, যেহেতু এটি একটি শিক্ষানবিশ প্রশ্ন, এটি ওপার বিবেচনা করেনি এমন ক্ষেত্রে এটি আমার মন্তব্য আশাবাদী সহায়ক হবে।
মাইকেল শ্যাপার

109

যদি আপনি জানেন যে নকল কী আপনার কাছে নেই বা আপনি নকল কীগুলির জন্য map2মানগুলি ওভাররাইট করতে চান তবে map1আপনি কেবল লিখতে পারেন

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

মানগুলি কীভাবে সংযুক্ত করা হয় তার উপরে যদি আপনার আরও নিয়ন্ত্রণের প্রয়োজন হয় তবে আপনি ব্যবহার করতে পারেন Map.merge জাভা 8-এ যুক্ত হওয়া , যা BiFunctionসদৃশ কীগুলির জন্য মানগুলি মার্জ করার জন্য ব্যবহারকারীর দ্বারা সরবরাহ করা ব্যবহার করে। mergeস্বতন্ত্র কী এবং মানগুলিতে পরিচালনা করে, তাই আপনাকে একটি লুপ বা ব্যবহার করতে হবে Map.forEach। এখানে আমরা সদৃশ কীগুলির জন্য স্ট্রিংগুলি একত্রীকরণ করি:

map3 = new HashMap<>(map1);
for (Map.Entry<String, String> e : map2.entrySet())
    map3.merge(e.getKey(), e.getValue(), String::concat);
//or instead of the above loop
map2.forEach((k, v) -> map3.merge(k, v, String::concat));

আপনি যদি জানেন যে আপনার কাছে সদৃশ কী নেই এবং এটি প্রয়োগ করতে চান, আপনি এমন একটি মার্জ ফাংশন ব্যবহার করতে পারেন যা একটি নিক্ষেপ করে AssertionError:

map2.forEach((k, v) ->
    map3.merge(k, v, (v1, v2) ->
        {throw new AssertionError("duplicate values for key: "+k);}));

এই নির্দিষ্ট প্রশ্ন থেকে একধাপ পিছনে, জাভা 8 স্ট্রিমের লাইব্রেরি সরবরাহ করে toMapএবং groupingBy সংগ্রহকারীদের । আপনি যদি বারবার কোনও লুপে মানচিত্র মার্জ করে থাকেন তবে আপনি আপনার গণনাটিকে স্ট্রিমগুলি ব্যবহার করতে পুনর্গঠন করতে সক্ষম হতে পারেন যা আপনার কোডকে স্পষ্ট করতে এবং একটি সমান্তরাল স্ট্রিম এবং সমবর্তী কালেক্টর ব্যবহার করে সহজ সমান্তরালতা সক্ষম করতে পারে।


46

জাভা 8 স্ট্রিম এপিআই ব্যবহার করে ওয়ান-লাইনার:

map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
       .collect(Collectors.toMap(Entry::getKey, Entry::getValue))

এই পদ্ধতির সুবিধাগুলির মধ্যে হ'ল মার্জ ফাংশনটি পাস করার ক্ষমতা যা একই কী রয়েছে এমন মানগুলির সাথে কাজ করবে, উদাহরণস্বরূপ:

map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
       .collect(Collectors.toMap(Entry::getKey, Entry::getValue, Math::max))

1
এটি সদৃশ কীগুলির জন্য অবৈধ স্টেট এক্সেপশনটি ছুঁড়ে ফেলবে
অর্পিত জে

1
@ArpitJ। এটি দ্বিতীয় পরিবর্তনের পুরো পয়েন্ট। কখনও কখনও আপনি ব্যতিক্রম চান, কখনও কখনও আপনি না।
অ্যালেক্স আর

36

দুটি মানচিত্র মার্জ করার জন্য জাভা 8 বিকল্প ওয়ান-লাইনার:

defaultMap.forEach((k, v) -> destMap.putIfAbsent(k, v));

পদ্ধতি রেফারেন্সের সাথে একই:

defaultMap.forEach(destMap::putIfAbsent);

অথবা তৃতীয় মানচিত্র সহ মূল মানচিত্র সমাধানের জন্য আদর্শ:

Map<String, Integer> map3 = new HashMap<String, Integer>(map2);
map1.forEach(map3::putIfAbsent);

এবং পেয়ারার সাথে দ্রুত পরিবর্তনশীল মানচিত্রে দুটি মানচিত্রকে মার্জ করার একটি উপায় যা কমপক্ষে সম্ভব মধ্যবর্তী অনুলিপি অপারেশনগুলি করে:

ImmutableMap.Builder<String, Integer> builder = ImmutableMap.<String, Integer>builder();
builder.putAll(map1);
map2.forEach((k, v) -> {if (!map1.containsKey(k)) builder.put(k, v);});
ImmutableMap<String, Integer> map3 = builder.build();

উভয় মানচিত্রে উপস্থিত মানগুলিকে ম্যাপিং ফাংশনের সাথে একত্রীকরণের প্রয়োজন হলে জাভা 8 এর সাথে দুটি মানচিত্র মার্জ করে দেখুন ।


32

আপনার চূড়ান্ত মানচিত্রের জন্য যদি আপনার পরিবর্তনের প্রয়োজন না হয় তবে জাভা এর ইন্টারফেস পদ্ধতির বিপরীতে এর এবং পদ্ধতি সহ পেয়ারা রয়েছে avaImmutableMapBuilderputAllMap , শৃঙ্খলিত করা যেতে পারে।

ব্যবহারের উদাহরণ:

Map<String, Integer> mergeMyTwoMaps(Map<String, Integer> map1, Map<String, Integer> map2) {
  return ImmutableMap.<String, Integer>builder()
      .putAll(map1)
      .putAll(map2)
      .build();
}

অবশ্যই, এই পদ্ধতিটি আরও জেনেরিক হতে পারে, ভারার্গস এবং লুপ টু ব্যবহার করতে পারে putAll Maps আর্গুমেন্ট ইত্যাদি থেকে তবে আমি একটি ধারণাটি দেখাতে চেয়েছিলাম।

এছাড়াও, ImmutableMapএবং এর Builderকয়েকটি সীমাবদ্ধতা রয়েছে (বা সম্ভবত বৈশিষ্ট্যগুলি?):

  • তারা নাল বৈরী (নিক্ষেপ) NullPointerException - মানচিত্রে কোনও কী বা মান যদি নাল হয়)
  • বিল্ডার সদৃশ কীগুলি গ্রহণ করবেন না ( IllegalArgumentExceptionনকল কীগুলি যুক্ত করা হলে নিক্ষেপ করা হবে)।


21

আপনি ব্যবহার করতে পারে Collection.addAll () অন্যান্য ধরনের, যেমন জন্য List, Set, ইত্যাদি জন্য Map, আপনি ব্যবহার করতে পারেন putAll


11

দুটি মানচিত্র সংযুক্ত করার জেনেরিক সমাধান যা সম্ভবত সাধারণ কীগুলি ভাগ করতে পারে:

জায়গায়:

public static <K, V> void mergeInPlace(Map<K, V> map1, Map<K, V> map2,
        BinaryOperator<V> combiner) {
    map2.forEach((k, v) -> map1.merge(k, v, combiner::apply));
}

একটি নতুন মানচিত্র ফিরে:

public static <K, V> Map<K, V> merge(Map<K, V> map1, Map<K, V> map2,
        BinaryOperator<V> combiner) {
    Map<K, V> map3 = new HashMap<>(map1);
    map2.forEach((k, v) -> map3.merge(k, v, combiner::apply));
    return map3;
}

2

একটি ছোট স্নিপেট আমি অন্যান্য মানচিত্র থেকে মানচিত্র তৈরি করতে খুব ঘন ঘন ব্যবহার করি:

static public <K, V> Map<K, V> merge(Map<K, V>... args) {
    final Map<K, V> buffer = new HashMap<>();

    for (Map m : args) {
        buffer.putAll(m);
    }

    return buffer;
}

2

আপনি HashMap<String, List<Integer>>উভয় হ্যাশম্যাপগুলিকে একীভূত করতে এবং একই কী দিয়ে যুক্ত উপাদানগুলি হারাতে এড়াতে পারেন।

HashMap<String, Integer> map1 = new HashMap<>();
HashMap<String, Integer> map2 = new HashMap<>();
map1.put("key1", 1);
map1.put("key2", 2);
map1.put("key3", 3);
map2.put("key1", 4);
map2.put("key2", 5);
map2.put("key3", 6);
HashMap<String, List<Integer>> map3 = new HashMap<>();
map1.forEach((str, num) -> map3.put(str, new ArrayList<>(Arrays.asList(num))));
//checking for each key if its already in the map, and if so, you just add the integer to the list paired with this key
for (Map.Entry<String, Integer> entry : map2.entrySet()) {
    Integer value = entry.getValue();
    String key = entry.getKey();
    if (map3.containsKey(key)) {
        map3.get(key).add(value);
    } else {
        map3.put(key, new ArrayList<>(Arrays.asList(value)));
    }
}
map3.forEach((str, list) -> System.out.println("{" + str + ": " + list + "}"));

আউটপুট:

{key1: [1, 4]}
{key2: [2, 5]}
{key3: [3, 6]}

2

খুব দেরী হয়েছে তবে আমার একই সমস্যা হওয়ার পরে আমি কী করেছি তা ভাগ করে নিতে দিন।

Map<String, List<String>> map1 = new HashMap<>();
map1.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map1.put("NZ", Arrays.asList("P1","P2","P3"));

Map<String, List<String>> map2 = new HashMap<>();
map2.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map2.put("NZ", Arrays.asList("P1","P2","P4"));

Map<String, List<String>> collect4 = Stream.of(map1, map2)
                .flatMap(map -> map.entrySet().stream())
                .collect(
                        Collectors.toMap(
                                Map.Entry::getKey,
                                Map.Entry::getValue,
                                (strings, strings2) -> {
                                    List<String> newList = new ArrayList<>();
                                    newList.addAll(strings);
                                    newList.addAll(strings2);
                                    return newList;
                                }
                        )
                );
collect4.forEach((s, strings) -> System.out.println(s+"->"+strings));

এটি নিম্নলিখিত আউটপুট দেয়

NZ->[P1, P2, P3, P1, P2, P4]
India->[Virat, Mahi, Rohit, Virat, Mahi, Rohit]

0
    HashMap<Integer,String> hs1 = new HashMap<>();
    hs1.put(1,"ram");
    hs1.put(2,"sita");
    hs1.put(3,"laxman");
    hs1.put(4,"hanuman");
    hs1.put(5,"geeta");

    HashMap<Integer,String> hs2 = new HashMap<>();
    hs2.put(5,"rat");
    hs2.put(6,"lion");
    hs2.put(7,"tiger");
    hs2.put(8,"fish");
    hs2.put(9,"hen");

    HashMap<Integer,String> hs3 = new HashMap<>();//Map is which we add

    hs3.putAll(hs1);
    hs3.putAll(hs2);

    System.out.println(" hs1 : " + hs1);
    System.out.println(" hs2 : " + hs2);
    System.out.println(" hs3 : " + hs3);

সদৃশ আইটেমগুলি যুক্ত করা হবে না (এটি হ'ল ডুপ্লিকেট কীগুলি) যখন আমরা এইচএস 3 প্রিন্ট করব আমরা কী 5 এর জন্য কেবল একটি মান পাব যা সর্বশেষ মান যুক্ত হবে এবং এটি ইঁদুর হবে। ** [সেটের ডুপ্লিকেট কীকে অনুমতি না দেওয়ার সম্পত্তি রয়েছে তবে মানগুলি নকল হতে পারে]


0

পদ্ধতি 1: একটি তালিকায় মানচিত্র রাখুন এবং তারপরে যোগদান করুন

public class Test15 {
public static void main(String[] args) {

    Map<String, List<String>> map1 = new HashMap<>();
    map1.put("London", Arrays.asList("A", "B", "C"));
    map1.put("Wales", Arrays.asList("P1", "P2", "P3"));

    Map<String, List<String>> map2 = new HashMap<>();
    map2.put("Calcutta", Arrays.asList("Protijayi", "Gina", "Gini"));
    map2.put("London", Arrays.asList( "P4", "P5", "P6"));
    map2.put("Wales", Arrays.asList( "P111", "P5555", "P677666"));

    System.out.println(map1);System.out.println(map2);



    // put the maps in an ArrayList

    List<Map<String, List<String>>> maplist = new ArrayList<Map<String,List<String>>>();
    maplist.add(map1);
    maplist.add(map2);
    /*
<T,K,U> Collector<T,?,Map<K,U>> toMap(

                                  Function<? super T,? extends K> keyMapper,

                                  Function<? super T,? extends U> valueMapper,

                                  BinaryOperator<U> mergeFunction)
    */

 Map<String, List<String>> collect = maplist.stream()
    .flatMap(ch -> ch.entrySet().stream())
    .collect(
            Collectors.toMap(

            //keyMapper,

            Entry::getKey,

            //valueMapper
            Entry::getValue,

            // mergeFunction
     (list_a,list_b) -> Stream.concat(list_a.stream(), list_b.stream()).collect(Collectors.toList())

            ));



    System.out.println("Final Result(Map after join) => " + collect);
    /*
    {Wales=[P1, P2, P3], London=[A, B, C]}
{Calcutta=[Protijayi, Gina, Gini], Wales=[P111, P5555, P677666], London=[P4, P5, P6]}
Final Result(Map after join) => {Calcutta=[Protijayi, Gina, Gini], Wales=[P1, P2, P3, P111, P5555, P677666], London=[A, B, C, P4, P5, P6]}
*/

}//main


}

পদ্ধতি 2: সাধারণ মানচিত্র একত্রিত

public class Test15 {
public static void main(String[] args) {

    Map<String, List<String>> map1 = new HashMap<>();
    map1.put("London", Arrays.asList("A", "B", "C"));
    map1.put("Wales", Arrays.asList("P1", "P2", "P3"));

    Map<String, List<String>> map2 = new HashMap<>();
    map2.put("Calcutta", Arrays.asList("Protijayi", "Gina", "Gini"));
    map2.put("London", Arrays.asList( "P4", "P5", "P6"));
    map2.put("Wales", Arrays.asList( "P111", "P5555", "P677666"));

    System.out.println(map1);System.out.println(map2);




    /*
<T,K,U> Collector<T,?,Map<K,U>> toMap(

                                  Function<? super T,? extends K> keyMapper,

                                  Function<? super T,? extends U> valueMapper,

                                  BinaryOperator<U> mergeFunction)
    */


Map<String, List<String>> collect = Stream.of(map1,map2)
    .flatMap(ch -> ch.entrySet().stream())
    .collect(
            Collectors.toMap(

            //keyMapper,

            Entry::getKey,

            //valueMapper
            Entry::getValue,

            // mergeFunction
     (list_a,list_b) -> Stream.concat(list_a.stream(), list_b.stream()).collect(Collectors.toList())

            ));



    System.out.println("Final Result(Map after join) => " + collect);
    /*
    {Wales=[P1, P2, P3], London=[A, B, C]}
{Calcutta=[Protijayi, Gina, Gini], Wales=[P111, P5555, P677666], London=[P4, P5, P6]}
Final Result(Map after join) => {Calcutta=[Protijayi, Gina, Gini], Wales=[P1, P2, P3, P111, P5555, P677666], London=[A, B, C, P4, P5, P6]}

*/

}//main


}

0

নীচের কোডে বর্ণিত হিসাবে আপনি মানচিত্রের জন্য পুটআল ফাংশন ব্যবহার করতে পারেন

HashMap<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("a", 1);
map1.put("b", 2);
map1.put("c", 3);
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
map1.put("aa", 11);
map1.put("bb", 12);
HashMap<String, Integer> map3 = new HashMap<String, Integer>();
map3.putAll(map1);
map3.putAll(map2);
map3.keySet().stream().forEach(System.out::println);
map3.values().stream().forEach(System.out::println);

0

স্নিপেটের নীচে একাধিক মানচিত্র লাগে এবং সেগুলি একত্রিত করে।

 private static <K, V> Map<K, V> combineMaps(Map<K, V>... maps) {
        if (maps == null || maps.length == 0) {
            return Collections.EMPTY_MAP;
        }

        Map<K, V> result = new HashMap<>();

        for (Map<K, V> map : maps) {
            result.putAll(map);
        }
        return result;
    }

ডেমো উদাহরণ লিঙ্ক।


-1

আপনি ব্যবহার করতে পারেন - addAll পদ্ধতি

http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html

তবে এই সমস্যাটি সবসময়ই রয়েছে - যদি আপনার দুটি হ্যাশ মানচিত্রের কোনও কী থাকে - তবে এটি দ্বিতীয় হ্যাশ মানচিত্রের চাবির মান সহ প্রথম হ্যাশ মানচিত্র থেকে কীটির মানকে ওভাররাইড করবে।

নিরাপদে থাকার জন্য - মূল মানগুলি পরিবর্তন করুন - আপনি কীগুলিতে উপসর্গ বা প্রত্যয় ব্যবহার করতে পারেন - (প্রথম হ্যাশ মানচিত্রের জন্য পৃথক উপসর্গ / প্রত্যয় এবং দ্বিতীয় হ্যাশ মানচিত্রের জন্য পৃথক উপসর্গ / প্রত্যয়)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.