Note that this answer was prior to your edit regarding the nature of the constructor, so some of this stuff may be extraneous, but the concepts still hold, so there's not much for me to change here except to add that your situation is the 4th bullet point in the first list below, so the possibility of modifying container1
via changes to container2
does exist, and you'll want to do a shallow or deep copy of that map rather than storing a reference to it.
Basically, "what happens to container1
" is exactly what you tell your code to do to container1
. Nothing tricky will happen behind the scenes.
So, there's no way to give a definitive answer from the information given, but from this line:
SomeContainer container2 = new SomeContainer(container1.getSomeEntity(),
container1.getSomeCrazyMapping());
The best we can tell you from what you've shown is that container1
will not be "modified" (depending on what you consider "modified") as long as:
- Your implementation of
getSomeEntity()
does not modify container1
, and
- Your implementation of
getSomeCrazyMapping()
does not modify container1
, and
- Your implementation of that constructor does not modify the parameters you pass in (e.g. by calling
clear()
on the map you pass it or something) in a way that causes container1
to be modified.
- Your implementation of that constructor does not create situations where you could modify
container1
via container2
later, e.g. you return the map directly in getSomeCrazyMapping()
, store a reference to it in container2
, then modify it via that reference.
I use the term "modified" loosely, since it really depends on your situation what you consider to be "modified", but no, nothing's going to just randomly happen, you have to analyze your code to see if you are explicitly modifying anything.
So to help you maintain careful control over things you have a few tools at your disposal. Here are some examples, and it's left as an exercise to you to figure out how you can use these effectively:
- Most maps have shallow "copy constructors", e.g.
HashMap
. References to the same key and value objects will be stored in the copy but it will at least be a different map.
- You've got e.g.
Object#clone
that you could implement on your containers, key and value objects, whatever. Note that some maps implement Cloneable
as well, see for example HashMap#clone
.
- You've got e.g.
Collections#unmodifiableMap
that you could use to wrap the return value of getSomeCrazyMapping()
if you want to programmatically ensure that nobody is adding/removing values to the map returned by that method.
- Here are some techniques for deep copying generic
Map
s, if you are sticking to generic Map
interfaces, which can be tricky.
Also don't forget you can do your copy on a "higher" level. For example if your containers have their own "add/insert" operations and their own "get"/iterator operations you can just not do the under-the-hood stuff and use your high level methods instead, which can greatly simplify your code (totally made up example), and remove dependence on the actual implementation details of your containers:
public SomeContainer (SomeContainer other) {
for (ExampleEntry entry : other.getEntries())
this.addEntry(entry);
}
Fwiw, this is the approach I'd probably take myself if my container implementations were getting complicated.
Just a small set of things you have to work with here. Documentation is also your friend, clearly document your invariants and assumptions like "Modifying the map returned by this method will modify this container" or "This constructor creates deep copies of its parameters", etc. Then stick to those in your implementations (and test!).