Java的隐藏功能 - ArrayList / 实例初始化程序澄清

5
Java的隐藏特性问题中,我对关于实例初始化器的答案很感兴趣。
我想知道如何修改这一行:
List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};

为了让它执行与嵌套的Arraylists相同的工作:
ArrayList<ArrayList<Integer>> numbers = ...

这是可能的吗?

5个回答

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

我不太推荐这种方法,因为它没有任何好处而创建了一个(匿名)类。

请使用以下任一方式:

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

或者

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

对于2级,您可以使用:

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

如果你真的想要,使用静态导入甚至可以将其简化为:

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

3

现在使用Arrays.asList的可变参数功能,列表的双括号初始化就不那么有趣了,您可以改用以下方法:

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

或者可以像这样与双括号初始化相结合:

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

但是它是否适合一行取决于您项目的代码格式化指南。这样写起来太啰嗦了,替代方案看起来更好。比如将数字放入字符串中并解析它。或者转换到支持文字列表语法的Scala、Groovy或Clojure。


双括号初始化在地图初始化方面仍然很有用,尽管例如Guava为小型地图提供了工厂方法。 - Christian Semrau
感谢大家的回答。我想知道是否有一种方法可以压缩你们展示的代码,以便将do add方法调用放在第一行。类似于:List<List<Integer>> numbers = new ArrayList<List<Integer>>(){add(Arrays.asList(1,2)),add(Arrays.asList(3,4))}; 这样做是否可行? - Heisenbug

2
当然,你也可以对内部的ArrayList执行相同的操作,但我认为这会变得非常难读...
    List<ArrayList<Integer>> numbers = new ArrayList<ArrayList<Integer>>()
    {
        {
            add(new ArrayList<Integer>()
            {
                {
                    add(1);
                    add(2);
                }
            });
            add(new ArrayList<Integer>()
            {
                {
                    add(1);
                    add(2);
                }
            });
        }
    };

尽管不会比传统方式更长或更糟糕(这取决于您的括号风格!)
    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);

其他答案中提供的Arrays.asList(1, 2)方法似乎是最好的。

2
我不会使用这个习惯用语来“简化”ArrayList声明。它看起来很酷,但是它不必要地创建了一个匿名的ArrayList子类,并且对我的口味来说看起来太“神奇”了…你需要编写易于下一个开发人员阅读和理解的代码。
相反,你应该考虑使用像Google Guava这样的库。
这里是一个使用Guava的Lists.newArrayList(E... elements)实用方法的示例:
    import com.google.common.collect.Lists;


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

或者更好地,仅在左侧使用List接口(应避免在变量声明中使用具体类):
    import com.google.common.collect.Lists;


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

如果您知道这些列表将是不可变的,最好使用ImmutableList
    import com.google.common.collect.ImmutableList;


    List<List<Integer>> numbers = ImmutableList.<List<Integer>>of(
            ImmutableList.of(1, 2),
            ImmutableList.of(3, 4)
    );

1

只需将 int 替换为 ArrayList<integer> 对象即可。

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

            {
                add(new ArrayList<Integer>());
                add(new ArrayList<Integer>());
            }
        };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接