[java] Efficiency of Java "Double Brace Initialization"?

In Hidden Features of Java the top answer mentions Double Brace Initialization, with a very enticing syntax:

Set<String> flavors = new HashSet<String>() {{
    add("vanilla");
    add("strawberry");
    add("chocolate");
    add("butter pecan");
}};

This idiom creates an anonymous inner class with just an instance initializer in it, which "can use any [...] methods in the containing scope".

Main question: Is this as inefficient as it sounds? Should its use be limited to one-off initializations? (And of course showing off!)

Second question: The new HashSet must be the "this" used in the instance initializer ... can anyone shed light on the mechanism?

Third question: Is this idiom too obscure to use in production code?

Summary: Very, very nice answers, thanks everyone. On question (3), people felt the syntax should be clear (though I'd recommend an occasional comment, especially if your code will pass on to developers who may not be familiar with it).

On question (1), the generated code should run quickly. The extra .class files do cause jar file clutter, and slow program startup slightly (thanks to @coobird for measuring that). @Thilo pointed out that garbage collection can be affected, and the memory cost for the extra loaded classes may be a factor in some cases.

Question (2) turned out to be most interesting to me. If I understand the answers, what's happening in DBI is that the anonymous inner class extends the class of the object being constructed by the new operator, and hence has a "this" value referencing the instance being constructed. Very neat.

Overall, DBI strikes me as something of an intellectual curiousity. Coobird and others point out you can achieve the same effect with Arrays.asList, varargs methods, Google Collections, and the proposed Java 7 Collection literals. Newer JVM languages like Scala, JRuby, and Groovy also offer concise notations for list construction, and interoperate well with Java. Given that DBI clutters up the classpath, slows down class loading a bit, and makes the code a tad more obscure, I'd probably shy away from it. However, I plan to spring this on a friend who's just gotten his SCJP and loves good natured jousts about Java semantics! ;-) Thanks everyone!

7/2017: Baeldung has a good summary of double brace initialization and considers it an anti-pattern.

12/2017: @Basil Bourque notes that in the new Java 9 you can say:

Set<String> flavors = Set.of("vanilla", "strawberry", "chocolate", "butter pecan");

That's for sure the way to go. If you're stuck with an earlier version, take a look at Google Collections' ImmutableSet.

This question is related to java performance collections initialization

The answer is


Here's the problem when I get too carried away with anonymous inner classes:

2009/05/27  16:35             1,602 DemoApp2$1.class
2009/05/27  16:35             1,976 DemoApp2$10.class
2009/05/27  16:35             1,919 DemoApp2$11.class
2009/05/27  16:35             2,404 DemoApp2$12.class
2009/05/27  16:35             1,197 DemoApp2$13.class

/* snip */

2009/05/27  16:35             1,953 DemoApp2$30.class
2009/05/27  16:35             1,910 DemoApp2$31.class
2009/05/27  16:35             2,007 DemoApp2$32.class
2009/05/27  16:35               926 DemoApp2$33$1$1.class
2009/05/27  16:35             4,104 DemoApp2$33$1.class
2009/05/27  16:35             2,849 DemoApp2$33.class
2009/05/27  16:35               926 DemoApp2$34$1$1.class
2009/05/27  16:35             4,234 DemoApp2$34$1.class
2009/05/27  16:35             2,849 DemoApp2$34.class

/* snip */

2009/05/27  16:35               614 DemoApp2$40.class
2009/05/27  16:35             2,344 DemoApp2$5.class
2009/05/27  16:35             1,551 DemoApp2$6.class
2009/05/27  16:35             1,604 DemoApp2$7.class
2009/05/27  16:35             1,809 DemoApp2$8.class
2009/05/27  16:35             2,022 DemoApp2$9.class

These are all classes which were generated when I was making a simple application, and used copious amounts of anonymous inner classes -- each class will be compiled into a separate class file.

The "double brace initialization", as already mentioned, is an anonymous inner class with an instance initialization block, which means that a new class is created for each "initialization", all for the purpose of usually making a single object.

Considering that the Java Virtual Machine will need to read all those classes when using them, that can lead to some time in the bytecode verfication process and such. Not to mention the increase in the needed disk space in order to store all those class files.

It seems as if there is a bit of overhead when utilizing double-brace initialization, so it's probably not such a good idea to go too overboard with it. But as Eddie has noted in the comments, it's not possible to be absolutely sure of the impact.


Just for reference, double brace initialization is the following:

List<String> list = new ArrayList<String>() {{
    add("Hello");
    add("World!");
}};

It looks like a "hidden" feature of Java, but it is just a rewrite of:

List<String> list = new ArrayList<String>() {

    // Instance initialization block
    {
        add("Hello");
        add("World!");
    }
};

So it's basically a instance initialization block that is part of an anonymous inner class.


Joshua Bloch's Collection Literals proposal for Project Coin was along the lines of:

List<Integer> intList = [1, 2, 3, 4];

Set<String> strSet = {"Apple", "Banana", "Cactus"};

Map<String, Integer> truthMap = { "answer" : 42 };

Sadly, it didn't make its way into neither Java 7 nor 8 and was shelved indefinitely.


Experiment

Here's the simple experiment I've tested -- make 1000 ArrayLists with the elements "Hello" and "World!" added to them via the add method, using the two methods:

Method 1: Double Brace Initialization

List<String> l = new ArrayList<String>() {{
  add("Hello");
  add("World!");
}};

Method 2: Instantiate an ArrayList and add

List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("World!");

I created a simple program to write out a Java source file to perform 1000 initializations using the two methods:

Test 1:

class Test1 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    List<String> l1 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    /* snip */

    List<String> l999 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    System.out.println(System.currentTimeMillis() - st);
  }
}

Test 2:

class Test2 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>();
    l0.add("Hello");
    l0.add("World!");

    List<String> l1 = new ArrayList<String>();
    l1.add("Hello");
    l1.add("World!");

    /* snip */

    List<String> l999 = new ArrayList<String>();
    l999.add("Hello");
    l999.add("World!");

    System.out.println(System.currentTimeMillis() - st);
  }
}

Please note, that the elapsed time to initialize the 1000 ArrayLists and the 1000 anonymous inner classes extending ArrayList is checked using the System.currentTimeMillis, so the timer does not have a very high resolution. On my Windows system, the resolution is around 15-16 milliseconds.

The results for 10 runs of the two tests were the following:

Test1 Times (ms)           Test2 Times (ms)
----------------           ----------------
           187                          0
           203                          0
           203                          0
           188                          0
           188                          0
           187                          0
           203                          0
           188                          0
           188                          0
           203                          0

As can be seen, the double brace initialization has a noticeable execution time of around 190 ms.

Meanwhile, the ArrayList initialization execution time came out to be 0 ms. Of course, the timer resolution should be taken into account, but it is likely to be under 15 ms.

So, there seems to be a noticeable difference in the execution time of the two methods. It does appear that there is indeed some overhead in the two initialization methods.

And yes, there were 1000 .class files generated by compiling the Test1 double brace initialization test program.


There's generally nothing particularly inefficient about it. It doesn't generally matter to the JVM that you've made a subclass and added a constructor to it-- that's a normal, everyday thing to do in an object-oriented language. I can think of quite contrived cases where you could cause an inefficiency by doing this (e.g. you have a repeatedly-called method that ends up taking a mixture of different classes because of this subclass, whereas ordinary the class passed in would be totally predictable-- in the latter case, the JIT compiler could make optimisations that are not feasible in the first). But really, I think the cases where it'll matter are very contrived.

I'd see the issue more from the point of view of whether you want to "clutter things up" with lots of anonymous classes. As a rough guide, consider using the idiom no more than you'd use, say, anonymous classes for event handlers.

In (2), you're inside the constructor of an object, so "this" refers to the object you're constructing. That's no different to any other constructor.

As for (3), that really depends on who's maintaining your code, I guess. If you don't know this in advance, then a benchmark that I would suggest using is "do you see this in the source code to the JDK?" (in this case, I don't recall seeing many anonymous initialisers, and certainly not in cases where that's the only content of the anonymous class). In most moderately sized projects, I'd argue you're really going to need your programmers to understand the JDK source at some point or other, so any syntax or idiom used there is "fair game". Beyond that, I'd say, train people on that syntax if you have control of who's maintaining the code, else comment or avoid.


Double-brace initialization is an unnecessary hack that can introduce memory leaks and other issues

There's no legitimate reason to use this "trick". Guava provides nice immutable collections that include both static factories and builders, allowing you to populate your collection where it's declared in a clean, readable, and safe syntax.

The example in the question becomes:

Set<String> flavors = ImmutableSet.of(
    "vanilla", "strawberry", "chocolate", "butter pecan");

Not only is this shorter and easier to read, but it avoids the numerous issues with the double-braced pattern described in other answers. Sure, it performs similarly to a directly-constructed HashMap, but it's dangerous and error-prone, and there are better options.

Any time you find yourself considering double-braced initialization you should re-examine your APIs or introduce new ones to properly address the issue, rather than take advantage of syntactic tricks.

Error-Prone now flags this anti-pattern.


To create sets you can use a varargs factory method instead of double-brace initialisation:

public static Set<T> setOf(T ... elements) {
    return new HashSet<T>(Arrays.asList(elements));
}

The Google Collections library has lots of convenience methods like this, as well as loads of other useful functionality.

As for the idiom's obscurity, I encounter it and use it in production code all the time. I'd be more concerned about programmers who get confused by the idiom being allowed to write production code.


Taking the following test class:

public class Test {
  public void test() {
    Set<String> flavors = new HashSet<String>() {{
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
    }};
  }
}

and then decompiling the class file, I see:

public class Test {
  public void test() {
    java.util.Set flavors = new HashSet() {

      final Test this$0;

      {
        this$0 = Test.this;
        super();
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
      }
    };
  }
}

This doesn't look terribly inefficient to me. If I were worried about performance for something like this, I'd profile it. And your question #2 is answered by the above code: You're inside an implicit constructor (and instance initializer) for your inner class, so "this" refers to this inner class.

Yes, this syntax is obscure, but a comment can clarify obscure syntax usage. To clarify the syntax, most people are familiar with a static initializer block (JLS 8.7 Static Initializers):

public class Sample1 {
    private static final String someVar;
    static {
        String temp = null;
        ..... // block of code setting temp
        someVar = temp;
    }
}

You can also use a similar syntax (without the word "static") for constructor usage (JLS 8.6 Instance Initializers), although I have never seen this used in production code. This is much less commonly known.

public class Sample2 {
    private final String someVar;

    // This is an instance initializer
    {
        String temp = null;
        ..... // block of code setting temp
        someVar = temp;
    }
}

If you don't have a default constructor, then the block of code between { and } is turned into a constructor by the compiler. With this in mind, unravel the double brace code:

public void test() {
  Set<String> flavors = new HashSet<String>() {
      {
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
      }
  };
}

The block of code between the inner-most braces is turned into a constructor by the compiler. The outer-most braces delimit the anonymous inner class. To take this the final step of making everything non-anonymous:

public void test() {
  Set<String> flavors = new MyHashSet();
}

class MyHashSet extends HashSet<String>() {
    public MyHashSet() {
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
    }
}

For initialization purposes, I'd say there is no overhead whatsoever (or so small that it can be neglected). However, every use of flavors will go not against HashSet but instead against MyHashSet. There is probably a small (and quite possibly negligible) overhead to this. But again, before I worried about it, I would profile it.

Again, to your question #2, the above code is the logical and explicit equivalent of double brace initialization, and it makes it obvious where "this" refers: To the inner class that extends HashSet.

If you have questions about the details of instance initializers, check out the details in the JLS documentation.


  1. This will call add() for each member. If you can find a more efficient way to put items into a hash set, then use that. Note that the inner class will likely generate garbage, if you're sensitive about that.

  2. It seems to me as if the context is the object returned by new, which is the HashSet.

  3. If you need to ask... More likely: will the people who come after you know this or not? Is it easy to understand and explain? If you can answer "yes" to both, feel free to use it.


I was researching this and decided to do a more in depth test than the one provided by the valid answer.

Here is the code: https://gist.github.com/4368924

and this is my conclusion

I was surprised to find that in most of the run tests the internal initiation was actually faster (almost double in some cases). When working with large numbers the benefit seems to fade away.

Interestingly, the case that creates 3 objects on the loop loses it's benefit rans out sooner than on the other cases. I am not sure why this is happening and more testing should be done to reach any conclusions. Creating concrete implementations may help to avoid the class definition to be reloaded (if that's what's happening)

However, it is clear that not much overhead it observed in most cases for the single item building, even with large numbers.

One set back would be the fact that each of the double brace initiations creates a new class file that adds a whole disk block to the size of our application (or about 1k when compressed). A small footprint, but if it's used in many places it could potentially have an impact. Use this 1000 times and you are potentially adding a whole MiB to you applicaiton, which may be concerning on an embedded environment.

My conclusion? It can be ok to use as long as it is not abused.

Let me know what you think :)


Every time someone uses double brace initialisation, a kitten gets killed.

Apart from the syntax being rather unusual and not really idiomatic (taste is debatable, of course), you are unnecessarily creating two significant problems in your application, which I've just recently blogged about in more detail here.

1. You're creating way too many anonymous classes

Each time you use double brace initialisation a new class is made. E.g. this example:

Map source = new HashMap(){{
    put("firstName", "John");
    put("lastName", "Smith");
    put("organizations", new HashMap(){{
        put("0", new HashMap(){{
            put("id", "1234");
        }});
        put("abc", new HashMap(){{
            put("id", "5678");
        }});
    }});
}};

... will produce these classes:

Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class

That's quite a bit of overhead for your classloader - for nothing! Of course it won't take much initialisation time if you do it once. But if you do this 20'000 times throughout your enterprise application... all that heap memory just for a bit of "syntax sugar"?

2. You're potentially creating a memory leak!

If you take the above code and return that map from a method, callers of that method might be unsuspectingly holding on to very heavy resources that cannot be garbage collected. Consider the following example:

public class ReallyHeavyObject {

    // Just to illustrate...
    private int[] tonsOfValues;
    private Resource[] tonsOfResources;

    // This method almost does nothing
    public Map quickHarmlessMethod() {
        Map source = new HashMap(){{
            put("firstName", "John");
            put("lastName", "Smith");
            put("organizations", new HashMap(){{
                put("0", new HashMap(){{
                    put("id", "1234");
                }});
                put("abc", new HashMap(){{
                    put("id", "5678");
                }});
            }});
        }};

        return source;
    }
}

The returned Map will now contain a reference to the enclosing instance of ReallyHeavyObject. You probably don't want to risk that:

Memory Leak Right Here

Image from http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/

3. You can pretend that Java has map literals

To answer your actual question, people have been using this syntax to pretend that Java has something like map literals, similar to the existing array literals:

String[] array = { "John", "Doe" };
Map map = new HashMap() {{ put("John", "Doe"); }};

Some people may find this syntactically stimulating.


Loading many classes can add some milliseconds to the start. If the startup isn't so critical and you are look at the efficiency of classes after startup there is no difference.

package vanilla.java.perfeg.doublebracket;

import java.util.*;

/**
 * @author plawrey
 */
public class DoubleBracketMain {
    public static void main(String... args) {
        final List<String> list1 = new ArrayList<String>() {
            {
                add("Hello");
                add("World");
                add("!!!");
            }
        };
        List<String> list2 = new ArrayList<String>(list1);
        Set<String> set1 = new LinkedHashSet<String>() {
            {
                addAll(list1);
            }
        };
        Set<String> set2 = new LinkedHashSet<String>();
        set2.addAll(list1);
        Map<Integer, String> map1 = new LinkedHashMap<Integer, String>() {
            {
                put(1, "one");
                put(2, "two");
                put(3, "three");
            }
        };
        Map<Integer, String> map2 = new LinkedHashMap<Integer, String>();
        map2.putAll(map1);

        for (int i = 0; i < 10; i++) {
            long dbTimes = timeComparison(list1, list1)
                    + timeComparison(set1, set1)
                    + timeComparison(map1.keySet(), map1.keySet())
                    + timeComparison(map1.values(), map1.values());
            long times = timeComparison(list2, list2)
                    + timeComparison(set2, set2)
                    + timeComparison(map2.keySet(), map2.keySet())
                    + timeComparison(map2.values(), map2.values());
            if (i > 0)
                System.out.printf("double braced collections took %,d ns and plain collections took %,d ns%n", dbTimes, times);
        }
    }

    public static long timeComparison(Collection a, Collection b) {
        long start = System.nanoTime();
        int runs = 10000000;
        for (int i = 0; i < runs; i++)
            compareCollections(a, b);
        long rate = (System.nanoTime() - start) / runs;
        return rate;
    }

    public static void compareCollections(Collection a, Collection b) {
        if (!a.equals(b) && a.hashCode() != b.hashCode() && !a.toString().equals(b.toString()))
            throw new AssertionError();
    }
}

prints

double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 34 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns

leak prone

I've decided to chime in. The performance impact includes: disk operation + unzip (for jar), class verification, perm-gen space (for Sun's Hotspot JVM). However, worst of all: it's leak prone. You can't simply return.

Set<String> getFlavors(){
  return Collections.unmodifiableSet(flavors)
}

So if the set escapes to any other part loaded by a different classloader and a reference is kept there, the entire tree of classes+classloader will be leaked. To avoid that, a copy to HashMap is necessary, new LinkedHashSet(new ArrayList(){{add("xxx);add("yyy");}}). Not so cute any more. I don't use the idiom, myself, instead it is like new LinkedHashSet(Arrays.asList("xxx","YYY"));


Mario Gleichman describes how to use Java 1.5 generic functions to simulate Scala List literals, though sadly you wind up with immutable Lists.

He defines this class:

package literal;

public class collection {
    public static <T> List<T> List(T...elems){
        return Arrays.asList( elems );
    }
}

and uses it thusly:

import static literal.collection.List;
import static system.io.*;

public class CollectionDemo {
    public void demoList(){
        List<String> slist = List( "a", "b", "c" );
        List<Integer> iList = List( 1, 2, 3 );
        for( String elem : List( "a", "java", "list" ) )
            System.out.println( elem );
    }
}

Google Collections, now part of Guava supports a similar idea for list construction. In this interview, Jared Levy says:

[...] the most heavily-used features, which appear in almost every Java class I write, are static methods that reduce the number of repetitive keystrokes in your Java code. It's so convenient being able to enter commands like the following:

Map<OneClassWithALongName, AnotherClassWithALongName> = Maps.newHashMap();

List<String> animals = Lists.immutableList("cat", "dog", "horse");

7/10/2014: If only it could be as simple as Python's:

animals = ['cat', 'dog', 'horse']

2/21/2020: In Java 11 you can now say:

animals = List.of(“cat”, “dog”, “horse”)


While this syntax can be convenient, it also adds a lot of this$0 references as these become nested and it can be difficult to step debug into the initializers unless breakpoints are set on each one. For that reason, I only recommend using this for banal setters, especially set to constants, and places where anonymous subclasses don't matter (like no serialization involved).


Efficiency aside, I rarely find myself wishing for declarative collection creation outside of unit tests. I do believe that the double brace syntax is very readable.

Another way to achieve the declarative construction of lists specifically is to use Arrays.asList(T ...) like so:

List<String> aList = Arrays.asList("vanilla", "strawberry", "chocolate");

The limitation of this approach is of course that you cannot control the specific type of list to be generated.


One property of this approach that has not been pointed out so far is that because you create inner classes, the whole containing class is captured in its scope. This means that as long as your Set is alive, it will retain a pointer to the containing instance (this$0) and keep that from being garbage-collected, which could be an issue.

This, and the fact that a new class gets created in the first place even though a regular HashSet would work just fine (or even better), makes me not want to use this construct (even though I really long for the syntactic sugar).

Second question: The new HashSet must be the "this" used in the instance initializer ... can anyone shed light on the mechanism? I'd have naively expected "this" to refer to the object initializing "flavors".

This is just how inner classes work. They get their own this, but they also have pointers to the parent instance, so that you can call methods on the containing object as well. In case of a naming conflict, the inner class (in your case HashSet) takes precedence, but you can prefix "this" with a classname to get the outer method as well.

public class Test {

    public void add(Object o) {
    }

    public Set<String> makeSet() {
        return new HashSet<String>() {
            {
              add("hello"); // HashSet
              Test.this.add("hello"); // outer instance 
            }
        };
    }
}

To be clear on the anonymous subclass being created, you could define methods in there as well. For example override HashSet.add()

    public Set<String> makeSet() {
        return new HashSet<String>() {
            {
              add("hello"); // not HashSet anymore ...
            }

            @Override
            boolean add(String s){

            }

        };
    }

I second Nat's answer, except I would use a loop instead of creating and immediately tossing the implicit List from asList(elements):

static public Set<T> setOf(T ... elements) {
    Set set=new HashSet<T>(elements.size());
    for(T elm: elements) { set.add(elm); }
    return set;
    }

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to performance

Why is 2 * (i * i) faster than 2 * i * i in Java? What is the difference between spark.sql.shuffle.partitions and spark.default.parallelism? How to check if a key exists in Json Object and get its value Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly? Most efficient way to map function over numpy array The most efficient way to remove first N elements in a list? Fastest way to get the first n elements of a List into an Array Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3? pandas loc vs. iloc vs. at vs. iat? Android Recyclerview vs ListView with Viewholder

Examples related to collections

Kotlin's List missing "add", "remove", Map missing "put", etc? How to unset (remove) a collection element after fetching it? How can I get a List from some class properties with Java 8 Stream? Java 8 stream map to list of keys sorted by values How to convert String into Hashmap in java How can I turn a List of Lists into a List in Java 8? MongoDB Show all contents from all collections Get nth character of a string in Swift programming language Java 8 Distinct by property Is there a typescript List<> and/or Map<> class/library?

Examples related to initialization

"error: assignment to expression with array type error" when I assign a struct field (C) How to set default values in Go structs How to declare an ArrayList with values? Initialize array of strings Initializing a dictionary in python with a key value and no corresponding values Declare and Initialize String Array in VBA VBA (Excel) Initialize Entire Array without Looping Default values and initialization in Java Initializing array of structures C char array initialization