1
Map<String, WriteToFileColumnsModel> temp = new ConcurrentHashMap<>(inputMap);
temp.keySet().removeAll(targetMap.keySet());
targetMap.putAll(temp);

targetMap = new ConcurrentHashMap<>(inputMap);

targetMap.putAll(inputMap);

inputMap.forEach(targetMap::putIfAbsent);

for (Map.Entry<String, WriteToFileColumnsModel> entry : inputMap.entrySet()) {
        targetMap.put(entry.getKey(), entry.getValue());
}

I checked all the related questions on Stack Over Flow and tried the above possible ways. When I do any of the above way, new instance isn't created. When I alter targetMap, inputMap is altered too.

Any help would be appreciated. Thanks in advance :)

djechlin
  • 59,258
  • 35
  • 162
  • 290
Nikitha
  • 373
  • 2
  • 18
  • I don't understand what you are trying to do. – djechlin Feb 09 '16 at 17:28
  • I am trying to create a new map with the same key value pairs from the existing map. But when I alter the new map, existing map shouldn't be altered – Nikitha Feb 09 '16 at 17:29
  • Mumble mumble. Get your terms straight - when you create a new map and then addAll(sourceMap) you *have* a new map. There is no way this doesn't work (as you claim). What *probably* happens is that you alter *objects* in the map, which are *of course* the same objects in the copied map. If you want copies of the objects *in* the map, you have to make copies for *each object* yourself. – Durandal Feb 09 '16 at 17:32
  • So you mean the values are the same instances as of the existing map? You are right. I was altering the value in the new map – Nikitha Feb 09 '16 at 17:34
  • Then you need a way to make copies of each object. This can range from simple to nearly impossible, depending on your WriteToFileColumnModel implementation. The process is called *deep clone*. – Durandal Feb 09 '16 at 17:37
  • What is wrong with `Map newMap = new SomeKindOfMap(oldMap)`? If you don't change the contents of the key and value Objects, which you probably shouldn't anyway, that will work. Not sure what is your issru. – user949300 Feb 09 '16 at 17:37

2 Answers2

4

You're confusing altering the map with altering the objects in the map.

First and foremost: I rarely need to do this. Complex objects, like any called Model, rarely should be copied. It may be better to just pass the map around directly, or write a wrapper class that has better control over how its data can be accessed or modified.

You need a deep copy, which means the classes in the map - String and WriteToFileColumnsModel - need to support their own clone operation. Actually, this is a half-lie - String is immutable so using a shallow copy is fine, since it can never change anyway.

As a simpler example consider a class

class Person {
    public String name; // can be altered
}

And a

List<Person> people = new ArrayList<>();
people.add(new Person("Bob"));

And you try to copy it

List<Person> otherPeople = new ArrayList<>(people);

And alter one...

people.get(0).name = "Sue";

And get the other one...

System.out.println(otherPeople.get(0).name); // prints "Sue"

This is the problem you are having in your copy.

You need to copy each WriteToFileColumnsModel individually, assuming this is supported. You probably will have to manually do this for each item in the map (or use some Java 8 bullcrap).

djechlin
  • 59,258
  • 35
  • 162
  • 290
2

To me, most of your solutions should work. However, I think the most straight forward way is this:

Map<String, WriteToFileColumnsModel> targetMap = new ConcurrentHashMap<>(inputMap);

I think there is another problem: You are changing the objects that are stored as value in the map. Since both maps point to the same objects, you change the value object for both maps at the same time.

Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51