Java 9 提供了如List.of()
,Map.of()
,Set.of()
等靜態工廠方法來建立不可變的集合(Immutable Collections)。
在Java 9以前可使用Guava函式庫來建立Immutable Collections物件。
ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");
Java 9的集合如List
,Set
,另外還有Map
都新增了of()
方法來建立Immutable Collections物件。
List<String> immutableList = List.of("a", "b", "c");
System.out.println(immutableList); // [a, b, c]
Set<String> immutableSet = Set.of("red", "yellow", "blue");
System.out.println(immutableSet); // [blue, yellow, red]
Map<Integer, String> immuableMap = Map.of(1, "one", 2, "two", 3, "three");
System.out.println(immuableMap); // {1=one, 3=three, 2=two}
Immutable Collections元素結構是不可被修改的,也就是一旦初始化後即不能新增刪除或修改集合中的元素,否則會丟出UnsupportedOperationException
。
而所謂"修改"Immutable Collections其實是指把修改後的元素放在另一個新建立的集合物件,此新的集合物件與原本"被修改"Immutable Collections物件擁有相同的結構。
Immutable Collections的不可變是指集合本身,並非指其所包含的元素。其包含的元素物件若非Immutable Object仍是可變的。
Map<Integer, String> mutableMap1 = new HashMap<>();
Map<Integer, String> mutableMap2 = new HashMap<>();
mutableMap1.put(1, "one");
List<Map<Integer, String>> immutableList = List.of(mutableMap1, mutableMap2);
immutableList.get(0).put(2, "two");
immutableList.forEach(System.out::println);
// {1=one, 2=two}
// {}
而Immutable與Unmodifiable並不相同,雖然兩者行為類似,也就是內容不可修改,不過Unmodifiable Collections中原本的集合仍是可變的,只不過包裝為不可修改;而Immutable Collections是根本上即不可變的。
例如下面試圖在unmodifiableList
新增元素,則拋出UnsupportedOperationException
錯誤。
List<String> mutableList = new ArrayList<>();
mutableList.add("a");
mutableList.add("b");
mutableList.add("c");
List<String> unmodifiableList = Collections.unmodifiableList(mutableList);
unmodifiableList.add("d"); // throw UnsupportedOperationException
但直接修改原本的可變集合mutableList
仍可正常執行。
List<String> mutableList = new ArrayList<>();
mutableList.add("a");
mutableList.add("b");
mutableList.add("c");
List<String> unmodifiableList = Collections.unmodifiableList(mutableList);
// unmodifiableList.add("d"); // throw UnsupportedOperationException
mutableList.add("d");
unmodifiableList.forEach(System.out::print); // abcd
使用Immutable Collections的優點:
- 安全性。因為不可變,所以可放心地傳送給第三方函式庫使用。
- 執行緒安全(Thread-safe),Immutable Collections是執行緒安全的,不用擔資源競爭(Race condition)的問題。
- 更好的效能,因為相較於可變的集合物件使用較少的記憶體空間
參考:
沒有留言:
張貼留言