Immutable Collections
ref: ImmutableCollectionsExplained · google/guava Wiki · GitHub
collection 的資料不一定需要隨時可以修改,如果可以任意修改,反而在某些時候,會造成問題。
不能修改的 collection,將資料傳給 untrusted libraries 使用,也不會被 library 任意修改資料
thread-safe,再多執行緒環境共用資料時,可避免同時修改發生問題
可節省 time, space
JDK 也有提供 Collections.unmodifiableXXX
methods,但還是有可能有以下問題
unwieldy and verbose: 使用時必須要在每一個地方,都先產生一份
unsafe: 只有在沒有其他地方,有儲存原本 collection 的 reference 時,這個 collection 才會是 immutable
inefficient: 資料結構還是跟原本 mutable collection 一樣,所以還是會有 concurrent modification check, 額外耗費的 space ...
@Test
public void jdk_unmodifiableMethod() {
List list = new ArrayList();
list.add("item1");
list.add("item2");
List unmodifiableList = Collections.unmodifiableList(list);
Exception exception = assertThrows(UnsupportedOperationException.class, () -> {
unmodifiableList.add("item3");;
});
assertEquals(exception.getClass().getName(), "java.lang.UnsupportedOperationException");
String actualMessage = exception.getMessage();
assertNull(actualMessage);
// 如果修改原本的 list,還是會影響到 unmodifiableList
list.add("item3");
assertEquals(unmodifiableList.size(), 3);
}
@Test
public void guava_immutable() {
List<String> stringArrayList = Lists.newArrayList("item1","item2");
ImmutableList<String> immutableList = ImmutableList.copyOf(stringArrayList);
Exception exception = assertThrows(UnsupportedOperationException.class, () -> {
immutableList.add("item3");
});
assertEquals(exception.getClass().getName(), "java.lang.UnsupportedOperationException");
String actualMessage = exception.getMessage();
assertNull(actualMessage);
// 如果修改原本的 list,不會影響到 immutableList
stringArrayList.add("item3");
assertEquals(stringArrayList.size(), 3);
assertEquals(immutableList.size(), 2);
}
Guava immutable collection 不能使用 null values,因為大部分的 code,都是必須要有值
產生 ImmutableXXX
collection 的方法:
使用 copyOf method ex:
ImmutableSet.copyOf(set)
使用 of method ex:
ImmutableSet.of("a", "b", "c")
orImmutableMap.of("a", 1, "b", 2)
使用 Builder
@Test
public void immutableCollection() {
// copyOf
List<String> stringArrayList = Lists.newArrayList("item1","item2");
ImmutableList<String> immutableList = ImmutableList.copyOf(stringArrayList);
// of
ImmutableSet.of("a", "b", "c", "a", "d", "b");
// Builder
Color color1 = new Color(0, 0, 255);
Color color2 = new Color(0, 255, 0);
ImmutableSet<Color> colors = ImmutableSet.of(color1, color2);
ImmutableSet<Color> newcolors =
ImmutableSet.<Color>builder()
.addAll(colors)
.add(new Color(0, 191, 255))
.build();
}
所有 immutable collections 都有透過 asList() 產生的 ImmutableList 的 view。
@Test
public void asList() {
ImmutableSet<String> set = ImmutableSet.of("a", "b", "c", "a", "d", "b");
String item0 = set.asList().get(0);
assertEquals(item0, "a");
}
Interface | JDK or Guava? | Immutable Version |
---|---|---|
Collection |
JDK | ImmutableCollection |
List |
JDK | ImmutableList |
Set |
JDK | ImmutableSet |
SortedSet /NavigableSet |
JDK | ImmutableSortedSet |
Map |
JDK | ImmutableMap |
SortedMap |
JDK | ImmutableSortedMap |
Multiset |
Guava | ImmutableMultiset |
SortedMultiset |
Guava | ImmutableSortedMultiset |
Multimap |
Guava | ImmutableMultimap |
ListMultimap |
Guava | ImmutableListMultimap |
SetMultimap |
Guava | ImmutableSetMultimap |
BiMap |
Guava | ImmutableBiMap |
ClassToInstanceMap |
Guava | ImmutableClassToInstanceMap |
Table |
Guava | ImmutableTable |
沒有留言:
張貼留言