views:

58

answers:

2

I normally do this to set a new Map to a private variable:

public static void setListaClausulas(Map<String, Clausula> nvLista) {
    listaClausulas = new TreeMap<String, Clausula>(nvLista);
}

I suppose this is ok to set a new copy of the nvLista and all it's members and not a reference, is it?

But now I have a Map inside another Map and I'm doing this:

public static void setListaClausulas(Map<String, Map<String, Clausula>> nvLista) {
    listaClausulas = new TreeMap<String, Map<String, Clausula>>(nvLista);
}

Is this the correct way to do it or do you recommend something else? What I want is to set a new copy of nvLista (and all it's elements) and not copy just the reference.

+1  A: 

I guess you are worried about the maps being passed in your method parameter will be mutated?

You need to create a deep-copy of the parameter. Various approaches are discussed in this SO question, deep-clone-utility-recomendation

EDIT: In response to comment, here's a coded version. This doesn't deep copy the Clausula instances, since they were not copied before - I'm assuming they're immutable.

public Map<String, Map<String, Clausula>> deepCopy(Map<String, Map<String, Clausula>> nvLista)
{
   Map<String, Map<String, Clausula>> target = new TreeMap<String, Map<String, Clausula>>();
   for (String key: nvLista.keySet()) {
       Map<String, Clausula> value = nvLista.get(key);
       target.put(key, new TreeMap<String,Clausula>(value));
   }
   return target;
}

However, nesting collection types like this quickly becomes unreadable. If you can change the code, it may help readability to create a wrapper object for the innermost map.

mdma
I need to use a manual approach and I can't use any of those solutions. How would I do it then for this specific case?
Nazgulled
Ok, answer updated with a code sample.
mdma
What's the wildcard for in this particular situation?
Nazgulled
Map<String, TreeMap> is not a subtype of Map<String,Map> so you need the wildcard. Try it and you'll see what I mean.
mdma
Just did and I can't spot any compiler errors or exceptions... Based on your suggestion, this is my full code: http://pastebin.org/286794
Nazgulled
There's a small difference, above, the map is TreeMap<String,TreeMap<String,Clausula>() - in your code it's Map<String,Map<Sring,Clausula>>, so you don't need the wildcard. I kept the TreeMap because I thought it was needed by your implementation. If it's clearer, I can update the code to use Map, and not TreeMap.
mdma
I see, thanks for the clarification on that. I created a question about wildcards here http://stackoverflow.com/questions/2922811/whats-the-purpuse-behind-wildcards-and-how-are-they-different-from-generics and I think I now see the difference. But I don't see the benefit in your solution. Is there a big difference in your implementation vs mine?
Nazgulled
Here, there's not much point to it. I think I've actually got stuck between two ideas while coding it. It's clearer without the wildcard, so I've removed it. I think I intended to return TreeMap<String,TreeMap> but seemed to have forgot that, and instead returned the wildcard. Either way, I hope the deep copy works for you!
mdma
It does :) I just wanted to know more about wildcards cause I'm still confused and can't seem to use them properly. But this is not the question for it.
Nazgulled
A: 

Deep copying is hard for general case, but you could do this to solve your particular problem:

static Map< String, Map< String, Clausula > > deepCopy (
        final Map< String, Map< String, Clausula > > source
    )
{
    final TreeMap< String, Map< String, Clausula> > result  =
        new TreeMap< String, Map<String,Clausula> >( );

    for (
        final Map.Entry< String, Map< String, Clausula> > cur :
            source.entrySet( )
    )
    {
        result.put(
            cur.getKey( ),
            new TreeMap< String, Clausula >( cur.getValue( ) )
        );
    }

    return result;
}
Alexander Pogrebnyak