Collections.unmodifiableCollection和Collections.unmodifiableSet

时间:2018-08-29 01:34:28

标签: java groovy collections set unmodifiable

假设我有以下Set

Set<String> fruits = new HashSet<String>();
fruits.add("Apple")
fruits.add("Grapes")
fruits.add("Orange")

如果我想创建一个防御性副本,以便在修改原始列表后副本不会反映出来,我可以这样做:

Set<String> unmodifiableFruits = Collections.unmodifiableSet(new HashSet(fruits))

所以,如果我这样做:

fruits.add("Pineapple")     
println(unmodifiableFruits)

unmodifiableFruits没有菠萝。

或者我可以这样:

Set<String> unmodifiableFruits = Collections.unmodifiableCollection(fruits)

结果相同,unmodifiableFruits没有菠萝。

问题:

  1. 假设我将fruits作为类的参数传递,则首选方法Collections.unmodifiableCollection()是吗?

原因是,我read在构造函数中声明new是一种不好的做法,如果我要使用Collections.unmodifiableSet(),则需要声明一个{{1 }}。

  1. 我为什么不能这样做?

    new HashSet<String>(fruits)

并使其返回不可修改的集合。

相反,我必须这样做:

Collections.unmodifiableSet(fruits)

是因为Set是一个接口,并且不知道要返回哪个实现?

1 个答案:

答案 0 :(得分:2)

Groovy增强了收集方法,这意味着它已将方法添加到标准收集类中。

其中一种方法是toSet()

  

将集合转换为集合。 始终返回一个新的集,即使该集合已经是一个集。

     

用法示例:

     
def result = [1, 2, 2, 2, 3].toSet()
assert result instanceof Set
assert result == [1, 2, 3] as Set

当您写这篇文章时:

Set<String> unmodifiableFruits = Collections.unmodifiableCollection(fruits)

这意味着进行.toSet()调用,以将Collection返回的unmodifiableCollection强制转换为Set隐式复制数据

当您写这篇文章时:

Set<String> unmodifiableFruits = Collections.unmodifiableSet(fruits)

返回的值已经是Set,因此不会调用toSet(),这意味着unmodifiableFruitsfruits共享数据。

这就是为什么在使用unmodifiableSet时必须通过添加new HashSet(...)显式复制数据的原因。

  

将集合传递到构造函数中时,是否使用Collections.unmodifiableCollection()是正确的方法?

绝对不是。 使用unmodifiableCollection()并分配给Set,隐式调用复制数据的toSet复制已执行的事实。

为确保代码可读性,即,阅读该代码的任何人(包括3年以下的您自己)都将理解其功能,请使用复制构造函数编写代码以显式复制数据。

当然,除非这是代码混淆的练习,否则在这种情况下,这是一个很好的误导性技巧。