java util Collections类offers,用于在任何现有列表周围创建“不可修改的”装饰器。但是我们都知道(或者在某些方面努力学习);它实际上只是一个最初传递给该调用的列表中的装饰器。装饰清单无法更改;但如果“原始”清单被修改,它将在封面下发生变化。
现在假设我有一些像
这样的课程class Whatever {
private final List<IDontCare> someElements;
public Whatever(List<IDontCare> incomingElements) {
someElements = unmodifiableCopyOf(incomingElements);
该类简单想要使用传入数据的真正不可修改的副本。好主意 - 但似乎没有干净/通用的方法来实现该方法unmodifiableCopyOf()
。
人们可以想到:
Tl;博士:这个问题真的没有“通用”解决方案(依赖“标准库”),它给了我一个真正无法修改的集合;基于其他一些收藏?
答案 0 :(得分:2)
选项#1
public Whatever(List srcList) {
Constructor<? extends List> c = srcList.getClass().getConstructor(Collection.class);
someElements = unmodifiableList(c.newInstance(srcList));
省略了try-catch。这适用于java.util
的列表,但不保证自定义列表。
选项#2
public Whatever(ArrayList srcList) {
someElements = unmodifiableList(new ArrayList(srcList));
public Whatever(LinkedList srcList) {
someElements = unmodifiableList(new LinkedList(srcList));
public Whatever(List srcList) {
someElements = unmodifiableList(new ArrayList(srcList)); // ok, no info
不要被这个解决方案欺骗,如果传递给构造函数的列表引用的类型为List
,则将使用第三个构造函数。
答案 1 :(得分:1)
是否有通用的方法从Collection / List / Set中创建一个不可修改的List / Set / Map?
是的!使用Collections.unmodifiable...
s。
Set<String> stuff = Collections.<String>unmodifiableSet(oldSet);
装饰清单无法更改;但如果&#34;原创&#34;列表已修改。
如果你不想要,那么错误在于处理原始集合而不是构建新集合。你应该在构建时复制它。
Set<String> uset = Collections.<String>unmodifiableSet(new HashSet<>(oldSet));
答案 2 :(得分:1)
Java 10完全添加了您想要的内容:copyOf
方法,您可以在这些方法中传递列表或集合或映射,并获取新副本,而不是Collections.unmodifiable…
生成的原始视图。
List.copyOf
Set.copyOf
Map.copyOf
List.copyOf
在Java 10及更高版本中,将可修改的List
传递到List.copyOf
。
List< Person > peopleUnmod = List.copyOf( people ) ;
生成的列表实际上是副本,与原始副本分开,而不是像Collections.unmodifiableList
那样查看原始副本。
引用List.copyOf
Javadoc:
以迭代顺序返回包含给定Collection元素的unmodifiable
List
。给定的Collection不能为null,并且不得包含任何null元素。如果随后修改了给定的Collection,则返回的List将不会反映出这种修改。
Set.copyOf
与之类似,Set
接口提供了一种Set.copyOf
方法来生成一组单独的新对象,这些对象与原始对象中的对象相同。
Map.copyOf
继续遵循这个主题,Map
界面提供了一种Map.copyOf
方法来生成一个单独的新映射,其中包含与原始键相同的键和值。