从集合框架概述:
不支持修改操作(如添加、删除和清除)的集合被称为不可修改的。不是不可修改的集合是可修改的。 另外保证Collection对象中的任何更改都不可见的集合称为不可变集合。不是不可变的集合是可变的。
我不明白其中的区别。 这里unmodifiable和immutable的区别是什么?
从集合框架概述:
不支持修改操作(如添加、删除和清除)的集合被称为不可修改的。不是不可修改的集合是可修改的。 另外保证Collection对象中的任何更改都不可见的集合称为不可变集合。不是不可变的集合是可变的。
我不明白其中的区别。 这里unmodifiable和immutable的区别是什么?
当前回答
Java™教程介绍了以下内容:
Unlike synchronization wrappers, which add functionality to the wrapped collection, the unmodifiable wrappers take functionality away. In particular, they take away the ability to modify the collection by intercepting all the operations that would modify the collection and throwing an UnsupportedOperationException. Unmodifiable wrappers have two main uses, as follows: To make a collection immutable once it has been built. In this case, it's good practice not to maintain a reference to the backing collection. This absolutely guarantees immutability. To allow certain clients read-only access to your data structures. You keep a reference to the backing collection but hand out a reference to the wrapper. In this way, clients can look but not modify, while you maintain full access.
我认为这是一个很好的解释,足以理解其中的区别。
其他回答
基本上不可修改集合是一个视图,所以它仍然可以间接地从其他一些可修改的引用中“修改”。也因为它只是另一个集合的只读视图,当源集合发生变化时,不可修改集合将始终显示最新的值。
然而,不可变集合可以被视为另一个集合的只读副本,不能被修改。在这种情况下,当源集合发生变化时,不可变集合不反映这些变化
下面是一个测试用例来可视化这种差异。
@Test
public void testList() {
List<String> modifiableList = new ArrayList<String>();
modifiableList.add("a");
System.out.println("modifiableList:"+modifiableList);
System.out.println("--");
//unModifiableList
assertEquals(1, modifiableList.size());
List<String> unModifiableList=Collections.unmodifiableList(
modifiableList);
modifiableList.add("b");
boolean exceptionThrown=false;
try {
unModifiableList.add("b");
fail("add supported for unModifiableList!!");
} catch (UnsupportedOperationException e) {
exceptionThrown=true;
System.out.println("unModifiableList.add() not supported");
}
assertTrue(exceptionThrown);
System.out.println("modifiableList:"+modifiableList);
System.out.println("unModifiableList:"+unModifiableList);
assertEquals(2, modifiableList.size());
assertEquals(2, unModifiableList.size());
System.out.println("--");
//immutableList
List<String> immutableList=Collections.unmodifiableList(
new ArrayList<String>(modifiableList));
modifiableList.add("c");
exceptionThrown=false;
try {
immutableList.add("c");
fail("add supported for immutableList!!");
} catch (UnsupportedOperationException e) {
exceptionThrown=true;
System.out.println("immutableList.add() not supported");
}
assertTrue(exceptionThrown);
System.out.println("modifiableList:"+modifiableList);
System.out.println("unModifiableList:"+unModifiableList);
System.out.println("immutableList:"+immutableList);
System.out.println("--");
assertEquals(3, modifiableList.size());
assertEquals(3, unModifiableList.size());
assertEquals(2, immutableList.size());
}
输出
modifiableList:[a]
--
unModifiableList.add() not supported
modifiableList:[a, b]
unModifiableList:[a, b]
--
immutableList.add() not supported
modifiableList:[a, b, c]
unModifiableList:[a, b, c]
immutableList:[a, b]
--
[不可更改和不可更改]
不可修改的集合(对象)仍然可以通过改变原始对象来改变。使用参考是可能的。
Java提供了几种方法来创建一个不可修改的映射:
Collections.unmodifiableMap () Java 9 Map.of(), Map.ofEntries()
如果我们讨论的是JDK不可修改*和番石榴不可修改*,实际上它们的区别还在于性能。如果不可变集合不是常规集合的包装器(JDK实现就是包装器),那么它们可以更快、更节省内存。 以番石榴团队为例:
JDK提供了集合。不可修改的xxx方法,但在我们看来,这些可以
<…>
低效:数据结构仍然有可变集合的所有开销,包括并发修改检查,哈希表中的额外空间等。
不可修改的和不可变的集合
创建一个可修改的地图
Map<String, String> modifiableMap = new HashMap();
modifiableMap.put(“1”,”one”);
modifiableMap.put(“2”,”two”);
modifiableMap.put(“3”,”three”);
从modifiableMap中创建一个unmodifiableMap
Map<String,String> unmodifiableMap = Collections.unmodifiableMap(modifiableMap);
unmodifiableMap.put(“4”,”Four”) ==>Exception
modifiableMap.put(“4”,”Four”); ==>Allowed, this will also reflect now in the unmodifiableMap , because unmodifiableMap() returns a wrapper around modifiableMap.
从modifiableMap创建一个immutableMap
Map<String,String> immutableMap = Collections.immutableMap(modifiableMap);
immutableMap.put(“5”,”Five”) ==>Exception
modifiableMap.put(“5”,”Five”); ==>Allowed, BUT this will NOT reflect now in the immutableMap, because immutableMap() returns a copy of the modifiableMap.
引用Java™教程:
Unlike synchronization wrappers, which add functionality to the wrapped collection, the unmodifiable wrappers take functionality away. In particular, they take away the ability to modify the collection by intercepting all the operations that would modify the collection and throwing an UnsupportedOperationException. Unmodifiable wrappers have two main uses, as follows: To make a collection immutable once it has been built. In this case, it's good practice not to maintain a reference to the backing collection. This absolutely guarantees immutability. To allow certain clients read-only access to your data structures. You keep a reference to the backing collection but hand out a reference to the wrapper. In this way, clients can look but not modify, while you maintain full access.
(强调我的)
这真的很概括。