在Java里,如何初始化一个List呢?

我知道,你可以毫不费力地写出这样的代码:

List<String> names = new ArrayList<String>();
 names.add("dreamhead");

这几乎是在Java 5/6风格的代码中随处可见的,但不知道你怎么想,反正这样的代码让我觉得很不爽。

首先,变量声明里存在重复,明明我已经知道它是一个String的List,还要再后面再说一次。如果你尝试过一些具有类型推演功能的语言,你就会知道,这种重复完全是可以由编译器处理掉的。Java 7也认为这样的代码不好,所以,它给我们提供了一个新的语法:

List<String> names = new ArrayList<>();

其实,即便是Java 5/6,我们也是有办法写出不那么冗余的代码。Guava已经为我们提供了一个解决方案,所以,同样的代码如果用Guava来写,它会是这样:

List<String> names = newArrayList();

这里,它利用了编译器的类型推演功能保证了类型的正确性。从代码上看,它甚至要比Java 7提供的解决方案键入的字符还少。

这只是第一步,再有我还要在List里面放入内容,让我们继续来看在Guava里面怎么做。

List<String> names = newArrayList("dreamhead");

一行代码搞定,因为支持变参,所以,我们甚至可以一次放入很多元素。但是,这不是终点。

在很多数情况下,使用List时,我们并不关心其具体的类型,只是把它当做一组数据来用,而并不是为了动态添加一些东西。这个时候,我们只要有一个不变的List就可以了。Guava里的ImmutableList就可以很好地把我们的意图表现出来。一方面,它实现了List接口,你可以把它当做一个List来用,另一方面,如果试图改变其中的内容,它会抛出异常。

就我们这里讨论的内容而言,它的初始化方法更为简单:

List<String> names = of("dreamhead");

这里讨论的只是List,但大多数内容同样适用于Set和Map,另外两种我们最常用的数据结构。

需要额外加以解释的是,of其实是为少量元素初始化打开的方便之门。所以,如果查看of的实现,你会发现List最多支持12个元素的处理,而Set只有6个,只是因为可变参数的存在,它可以支持到很多。但是,Map的则不同,它只有5对,因为它的键值对必须成对出现。如果你需要元素很大的ImmutableMap,一个更好的解决方法是采用Builder,下面是一个例子:

ImmutableMap<String, String> contentTypeMap = ImmutableMap.<String, String>builder()
            .put("png", "image/png")
            .put("gif", "image/gif")
            .put("jpg", "image/jpeg")
            .put("jpeg", "image/jpeg")
            .put("tiff", "image/tiff")
            .put("css", "text/css")
            .put("html", "text/html")
            .put("txt", "text/plain")
            .put("js", "application/x-javascript")
            .put("json", "application/json")
            .put("pdf", "application/pdf")
            .put("zip", "application/zip")
            .put("xml", "text/xml")
            .build();

在程序设计领域,有一个经典的说法,语言设计就是程序库设计,程序库设计就是语言设计。像List、Map这样的集合类型,有些语言把它放进了语法,使得它用起来更简单。像Java这样做起事来一板一眼的程序设计语言,如果有了好的程序库支撑,也可以让它相对方便,Guava在这方面做了一个很好的尝试。

对普通的Java程序员而言,是时候抛弃繁重的Java旧语法,拥抱新时代的Java了。