5

In the Hidden Features of Java question, I was interested in the answer about instance initializers.

I was wondering how to modify this line :

List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};

in order to make it perform the same job with nested Arraylists:

ArrayList<ArrayList<Integer>> numbers = ...

is that possible?

Community
  • 1
  • 1
Heisenbug
  • 38,762
  • 28
  • 132
  • 190

5 Answers5

4
List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};

I don't really recommend this approach, as it creates an (anonymous) class for no good reason.

Use either:

List<Integer> numbers = Arrays.asList(1, 2);

or

List<Integer> numbers = new ArrayList<Integer>(Arrays.asList(1, 2));

For 2 levels, you can use:

List<List<Integer>> numbers = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(2,3,4));

With a static import you could even reduce it to this, if you really want to:

List<List<Integer>> numbers = asList(asList(1, 2), asList(2,3,4));
Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
Puce
  • 37,247
  • 13
  • 80
  • 152
3

Double-brace initialization got a lot less interesting for lists now that Arrays.asList takes varargs, you can do this instead:

List<List<Integer>> numbers = new ArrayList<List<Integer>>();
numbers.add(Arrays.asList(1,2));
numbers.add(Arrays.asList(3,4));

Or combine with double-brace initialization like this:

List<List<Integer>> numbers = new ArrayList<List<Integer>>() {{add(Arrays.asList(1,2)); add(Arrays.asList(3,4));}};

but whether it fits on one line depends on your project's code-formatting guidelines. This is so horribly verbose that alternatives start to look good. Like putting the numbers into a string and parsing it. Or switching to Scala, Groovy, or Clojure, all of whom support literal list syntax.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • Double-brace initialization may still be useful for map initialization, although e.g. Guava has factory methods for small maps. – Christian Semrau May 26 '11 at 18:49
  • thanks all for the answer..i was wondering if there is a way to condense the code you showed us, in order put the do add method calls in the first line. Something like : List> numbers = new ArrayList>(){add(Arrays.asList(1,2)),add(Arrays.asList(3,4))}; is that possible? – Heisenbug May 26 '11 at 19:03
2

And of course you can do the same for the inner ArrayLists:, though I think it becomes pretty unreadable...

    List<ArrayList<Integer>> numbers = new ArrayList<ArrayList<Integer>>()
    {
        {
            add(new ArrayList<Integer>()
            {
                {
                    add(1);
                    add(2);
                }
            });
            add(new ArrayList<Integer>()
            {
                {
                    add(1);
                    add(2);
                }
            });
        }
    };

though not wildly longer or worse than the conventional way (depending on your brace style!)

    List<ArrayList<Integer>> numbers = new ArrayList<ArrayList<Integer>>();
    ArrayList<Integer> list1 = new ArrayList<Integer>();
    ArrayList<Integer> list2 = new ArrayList<Integer>();
    list1.add(1);
    list1.add(2);
    list2.add(1);
    list2.add(2);
    numbers.add(list1);
    numbers.add(list2);

The Arrays.asList(1, 2) approach given in other answers seems nicest of all.

DNA
  • 42,007
  • 12
  • 107
  • 146
2

I would not use this idiom to "simplify" ArrayList declarations. It looks cool, but it needlessly creates an anonymous subclass of ArrayList, and it looks too "magical" for my tastes... You want code that is both readable and understandable by the next developer.

You should instead consider using a library such as Google Guava.

Here is an example using Guava's Lists.newArrayList(E... elements) utility method:

    import com.google.common.collect.Lists;


    List<ArrayList<Integer>> numbers = Lists.newArrayList(
            Lists.newArrayList(1, 2),
            Lists.newArrayList(3, 4)
    );

Or, even better, using only the List interface on the left-hand side (you should avoid using concrete classes in your variable declarations):

    import com.google.common.collect.Lists;


    List<List<Integer>> numbers = Lists.<List<Integer>>newArrayList(
            Lists.newArrayList(1, 2),
            Lists.newArrayList(3, 4)
    );

If you know these lists will be immutable, it's even better to use ImmutableList:

    import com.google.common.collect.ImmutableList;


    List<List<Integer>> numbers = ImmutableList.<List<Integer>>of(
            ImmutableList.of(1, 2),
            ImmutableList.of(3, 4)
    );
Etienne Neveu
  • 12,604
  • 9
  • 36
  • 59
1

Just replace int with object of ArrayList<integer>

List<ArrayList<Integer>> numbers = new ArrayList<ArrayList<Integer>>() {

            {
                add(new ArrayList<Integer>());
                add(new ArrayList<Integer>());
            }
        };
jmj
  • 237,923
  • 42
  • 401
  • 438