为了账号安全,请及时绑定邮箱和手机立即绑定

Collections.unmodifiableCollection

Collections.unmodifiableCollection

慕莱坞森 2021-08-19 16:13:27
假设我有以下内容 SetSet<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没有菠萝。问题:假设如果我fruits作为参数传递给一个类,首选方法是Collections.unmodifiableCollection()?原因是,我读过new在构造函数中声明是一种不好的做法,如果我要使用Collections.unmodifiableSet(),我需要声明一个new HashSet<String>(fruits).为什么我不能这样做?Collections.unmodifiableSet(fruits)并让它返回一个不可修改的集合。相反,我必须这样做:Collections.unmodifiableSet(new HashSet<String>(fruits))是不是因为 Set 是一个接口并且它不知道要返回哪个实现?
查看完整描述

1 回答

?
潇湘沐

TA贡献1816条经验 获得超6个赞

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返回的 by强制unmodifiableCollection转换为 a Set,隐式复制数据。


当你写这个:


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

返回的值已经是 a Set,所以toSet()没有被调用,这意味着unmodifiableFruits和fruits共享数据。


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


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


绝对不。使用unmodifiableCollection()和分配 aSet,隐式调用toSet哪个复制数据,隐藏了执行副本的事实。


为确保代码可读性,即任何阅读代码的人(包括 3 年后的您)都会理解它的作用,请使用复制构造函数编写代码以显式复制数据。


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


查看完整回答
反对 回复 2021-08-19
  • 1 回答
  • 0 关注
  • 184 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信