3

I have a nested collection in the form:

HashMap<String, HashMap<String, List<String>>> errorList;

Now I initialize it inline using double braces like this

errorList.put(tempName, new HashMap<String, List<String>>() {{
    put("upl", new ArrayList<String>() {{ add("Y"); add("Upload Success"); }});
}});

This lies in a foreach loop with the value of tempName changing in every iteration. I did this because i couldn't use instances of List<String> or HashMap<String,List<String>> because every time i changed the value in that instance it is reflected in the collection it is nested in. So i am forced to create new instances with double brace initialization.

Thing is: I want to use a list object. Instead of

new ArrayList<String>() {{ add("Y"); add("Upload Success"); }}

I want to use a variable.

How can I do this?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
kaattaalan
  • 61
  • 7
  • 2
    If you want to use a variable, why don't you just do it? – M. Prokhorov May 10 '17 at 11:49
  • I’m afraid I haven’t fully understood your problem. Could you [create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve), please? – Ole V.V. May 10 '17 at 12:06
  • This code is scary at least, you should have objects instead of so many collections. This is just unmaintainable. – Marc May 10 '17 at 12:25
  • I'm just using it inside a spring controller so that i can pass a list of errors to populate an Error table in the view(jsp). The scope is within that controller method and view. I figured this data object would grant me large flexibility in the view side. – kaattaalan May 10 '17 at 12:32
  • Possible duplicate of [Efficiency of Java "Double Brace Initialization"?](https://stackoverflow.com/questions/924285/efficiency-of-java-double-brace-initialization) – kaattaalan May 31 '17 at 06:21

1 Answers1

5

Instead of:

new ArrayList<String>() {{ add("Y"); add("Upload Success"); }}

you may use:

Arrays.asList("Y", "Upload Success")

This gives you a fixed-size list. If you want to be able to add or remove elements later, convert it into an ArrayList:

new ArrayList<>(Arrays.asList("Y", "Upload Success"))

And of course you can put this list into its own variable before putting it into your map structure.

If you want to put either [Y, Upload Success] or [N, Upload Failed] and make sure the lists aren’t shared between map entries, here’s a suggestion: First, outside your loop:

final List<String> successList = Arrays.asList("Y", "Upload Success");
final List<String> failureList = Arrays.asList("N", "Upload Failed");

Then inside your loop:

if (wasSuccessful) {
    errorList.put(tempName,
                  Collections.singletonMap("upl", new ArrayList<>(successList)));
} else {
    errorList.put(tempName,
                  Collections.singletonMap("upl", new ArrayList<>(failureList)));
}

You may take the idea one step further and build the maps outside the loop. And again, if you want the inner map to be a HashMap, just convert into one: new HashMap<>(Collections.singletonMap("upl", new ArrayList<>(successList))).

You notice I have avoided the double brace initialization completely. While it’s brief, it has an overhead both conceptually and performancewise. You are creating a new anonymous subclass each time, which I don’t find warranted.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • could you tell me what singletonMap does in this code?. The inner hashmap has other keys also (4 of them). They represent different error types present in some uploaded data – kaattaalan May 10 '17 at 12:34
  • Such a question is answered most easily be consulting [the `Collections` documentation](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#singletonMap-K-V-). And yes, since you want to put more elements in it, convert it to a `HashMap` as I described. – Ole V.V. May 10 '17 at 12:38