在 Java 中初始化 List
的五種方法
Java 中經常需要使用到 List,下面簡單介紹幾種常見的初始化方式杨帽。
1.構造 List
后使用 List.add
初始化
List<String> stringList = new LinkedList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
這是最常規(guī)的做法剑辫,用起來不太方便撩匕。
2.使用 {{}}
雙括號語法
List<String> stringList = new LinkedList<String>(){{
add("a");
add("b");
add("c");
}};
這種方式相對方便了一些衅枫。
外層的 {}
定義了一個 LinkedList 的匿名內部類。內層的 {}
的定義了一個實例初始化代碼塊。 這個代碼塊在初始化內部類時執(zhí)行。所以這里相當于定義了一個匿名內部類渗钉,并使用 add
添加元素來初始化。
這種方式有幾個缺點:
- 使用匿名內部類钞钙,會有效率上的損失鳄橘。當然在大多數情況下,這點效率都是可接受的芒炼。
- 靜態(tài)內部類持有所在外部類的引用瘫怜。如果需要將 List 返回給到其他地方使用,可能造成內存泄漏本刽。
3.使用 Arrays.asList
List<String> stringList = Arrays.asList("a", "b", "c");
這種方式使用了 java.util.Arrays
的靜態(tài)方法鲸湃。寫法上比之前的兩種都更簡潔,也沒有構造匿名內部類的效率問題子寓。
但也有幾點需要注意:
-
Arrays.asList
返回的是Arrays
的靜態(tài)內部類(靜態(tài)內部類不持有所在外部類的引用)暗挑。
這個內部類繼承自 AbstractList
,實現(xiàn)了 RandomAccess
斜友,內部使用了一個數組來存儲元素炸裆。但是不支持增刪元素。這點需要注意鲜屏。如果只是使用 Arrays.asList
來初始化常量烹看,那么這點就不算什么問題了。
-
Arrays.asList
的參數如果是基本類型的數組時洛史,需要留意返回值可能和你預期的不同惯殊。
int[] intArray = new int[]{1, 2, 3};
Integer[] integerArray = new Integer[]{1, 2, 3};
List<int[] > intArrayList = Arrays.asList(intArray);
List<Integer> integerList = Arrays.asList(integerArray);
List<Integer> integerList2 = Arrays.asList(1, 2, 3);
這里 Arrays.asList(intArray)
的返回值是 List<int[]>
而不是 List<Integer>
。這一點也算不上問題也殖,只是使用時需要留意靠胜。如果能在 Java 中做到盡量使用 List 和 Integer,盡量避免使用 int 等基本類型和 []
這種較為底層的數據結構即可避免毕源。
說點題外話:
Java 終究還是不能稱之為完全面向對象浪漠。畢竟保留了基本數據類型這種東西。誠然基本數據類型使用時比相應的封裝類型效率要更高霎褐。但也給使用過程中帶來了一些困惑:到底該用基本類型址愿,還是封裝類型,什么時候該用這個冻璃,什么時候該用哪個响谓?雖然 Java 提供給了用戶更多的選擇损合,但有種將難題丟給用戶的感覺。在我看來娘纷,Java 相比的 C++ 一個優(yōu)點嫁审,就是很多事情有了限制,有較為明確清晰的定義赖晶,減少了模棱兩可律适,更容易理解。但基本數據類型這里遏插,感覺還是 Java 作為一門改善了 C++ 缺點的語言留下的一些影子捂贿。
雖然本文是在講初始化 List
,但這里的 {{}}
雙括號語法同樣可用于初始化 Map
等其他眾多類型胳嘲。相對而言厂僧,Arrays.asList
就只能用于初始化 List
類型了。
4. 使用 Stream
(JDK8)
List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());
使用了 JDK8 的 Stream 來初始化了牛。 單純初始化 List颜屠,使用 Stream 有點大材小用了。
5. 使用 Lists
(JDK9)
List<String> list = Lists.newArrayList("a", "b", "c");
這個和 Arrays.asList
一樣簡潔清晰鹰祸。