博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Collections.unmodifiableMap
阅读量:6994 次
发布时间:2019-06-27

本文共 2624 字,大约阅读时间需要 8 分钟。

1. Collections.unmodifiableMap 是什么?

Java的官方解释:

public static 
 
 unmodifiableMap(
 m)
Returns an unmodifiable view of the specified map. This method allows modules to provide users with "read-only" access to internal maps. Query operations on the returned map "read through" to the specified map, and attempts to modify the returned map, whether direct or via its collection views, result in an 
UnsupportedOperationException.

翻译过来就是:该方法返回了一个map的不可修改的视图umap, 为用户提供了一种生成只读容器的方法。如果尝试修改该容器umap, 将会抛出UnsupportedOperationException异常。

2. Collections.unmodifiableMap 能做什么?

在《重构-改善既有代码逻辑》一书中提到了封装集合的功能(Encapsulate Collection)。

我们在类中经常需要返回一个集合,比如mapA。如果直接返回成员变量mapA本身的话,相当于对外暴露了集合的引用,外部就可以随意修改该对象的集合,该对象可能对修改都一无所知,属性却发生了变化。

一种解决方法,就是将该集合修饰为private, 在返回集合的方法中采用Collections.unmodifiableMap(mapA),返回mapA的一个不可变的副本。且该方法要比我们自己去复制一个副本效率要高。

3. Collections.unmodifiableMap 构造的map真的不可修改吗?

遗憾的是该结论并不总是成立。对于map<key, value>中的内容value, unmodifiableMap仅仅保证的是它的引用不能被修改,如果value对应的是一个可变对象,那么该unmodifiableMap的内容还是可变的。见实例:

 

1 public class UnmodifiableMap { 2  3     public static void main(String[] args) { 4  5         Map
map = new HashMap
(); 6 Student tom = new Student("tom", 3); 7 map.put("tom", tom); 8 map.put("jerry", new Student("jerry", 1)); 9 10 Map
unmodifiableMap = Collections.unmodifiableMap(map);11 // unmodifiableMap.put("tom", new Student("tom", 11)); // tag112 tom.setAge(11); // tag213 System.out.println(unmodifiableMap);14 }15 16 }17 18 // mutable19 class Student {20 private String name;21 private int age;22 23 public Student(String name, int age) {24 this.name = name;25 this.age = age;26 }27 28 public String getName() {29 return name;30 }31 32 public void setName(String name) {33 this.name = name;34 }35 36 public int getAge() {37 return age;38 }39 40 public void setAge(int age) {41 this.age = age;42 }43 44 @Override45 public String toString() {46 return "Student{" +47 "name='" + name + '\'' +48 ", age=" + age +49 '}';50 }51 }

 

代码中Student 对象是可变对象。在tag1处,尝试更换为另一个对象,引用发生了变化,会抛出UnsupportedOperationException异常。unmodifiableMap阻止了对其的修改

但如果引用不变,见tag2处,还是tom, 但对该对象内容作了修改,unmodifiableMap并未阻止该行为。unmodifiableMap的内容变为了

{jerry=Student{name='jerry', age=1}, tom=Student{name='tom', age=11}}

所以为了线程安全,在使用Collections.unmodifiableMap的同时,尽量让其中的内容实现为不可变对象。

 

 

转载于:https://www.cnblogs.com/dreamysmurf/p/6253737.html

你可能感兴趣的文章
第二十节,基本数据类型,集合set、综合应用新数据更新老数据
查看>>
架构设计:前后端分离之Web前端架构设计
查看>>
C#动态调用WCF接口(2)
查看>>
SQLAlchemy增删改查基本操作,及SQL基本技能样码(join,group)
查看>>
Python中获取当前日期的格式
查看>>
win10 安装visual studio 2015遇到的坑
查看>>
机器学习——基于概率论的分类方法:朴素贝叶斯
查看>>
Spring中的Interceptor 拦截器 专题
查看>>
mysql计算连续天数,mysql连续登录天数,连续天数统计
查看>>
用离散傅里叶变换实现线性卷积
查看>>
IIS7.5配置SSL
查看>>
Hadoop HBase概念学习系列之HBase里的HRegion(五)
查看>>
HBase、Hive、MapReduce、Hadoop、Spark 开发环境搭建后的一些步骤(export导出jar包方式 或 Ant 方式)...
查看>>
[Angular Directive] 3. Handle Events with Angular 2 Directives
查看>>
easyUi load方法重新加载表单的数据
查看>>
mysql-mmm 安装配置(双主)
查看>>
NeHe OpenGL教程 第三十六课:从渲染到纹理
查看>>
eclipse使用sublime配色(转)
查看>>
进程、线程、socket套接字-资源大小 & 切换代价
查看>>
Linux命令(1) - 查看内存使用情况: free -hm
查看>>