0、前言

工作忙起来后,许久不看算法,竟然DFA敏感词算法都要看好一阵才能理解。。。真是和三阶魔方还原手法一样,田园将芜,非常可惜啊。

在DFA算法中,第一步是需要理解它的数据结构,在此基础上,涉及到一些Hashmap的赋值。这里的赋值非常有趣,三个Hashmap翻来覆去赋值,就解决了敏感词表的初始化。

里面都是属于下文中的Hashmap“浅拷贝”,那么究竟Java中的Hashmap有哪些拷贝方法呢?

1、测试代码

HashMap hm_source = new HashMap();
HashMap hm_clone = new HashMap();
hm_source.put("1", "1"); // hashmap deep clone method 1
hm_clone = (HashMap)hm_source.clone();
// hashmap deep clone method 2
hm_clone.putAll(hm_source);// hashmap shadow clone
// hm_b = hm_a; hm_source.put("2", "2");
System.out.println("hm_source增加元素后,hm_source:"+hm_source);
System.out.println("hm_source增加元素后,hm_clone:"+hm_clone); System.out.println("是否指向同一内存地址:"+(hm_source==hm_clone));
System.out.println("第一个元素是否指向同一内存地址:"+(hm_source.get(1)==hm_clone.get(1)));

上面介绍了两种Hashmap深拷贝的方法,分别是hashmap.clone()和hashmap.putAll(hm_source),效果一样,输出如下:

hm_source增加元素后,hm_source:{1=1, 2=2}
hm_source增加元素后,hm_clone:{1=1}
是否指向同一内存地址:false
第一个元素是否指向同一内存地址:true

那么浅拷贝呢?(代码中注释的那段,直接等号=赋值),输出如下:

hm_source增加元素后,hm_source:{1=1, 2=2}
hm_source增加元素后,hm_clone:{1=1, 2=2}
是否指向同一内存地址:true
第一个元素是否指向同一内存地址:true

2、输出解析

不难发现,深浅拷贝确实如其名,

深拷贝:两个Hashmap对象似乎彻底无关,互相增加修改元素后,都不影响对方;

浅拷贝:两个Hashmap对象就是“软链接ln”,互相牵制,你改动了,我也跟着变。

3、上述猜想是否正确?

我党的思想路线是实事求是,预想剖析根本区别,大家可以看看JDK clone函数的源码。

但是从现象我们得到的初步结论有几点:

  1. 浅拷贝的两个对象使用的内存地址相同,深拷贝的对象地址“另立门户”;
  2. 深拷贝的两个对象也不完全“彻底无关”,仅仅是复制了元素的引用;

关于结论3.2,我也是在 HashMap的clone方法 博文中学习到了,里面使用的Hashmap元素是Bean类型的,深拷贝下的元素修改,也会“打断骨头连着筋”地让两个Hashmap同时更新。

但是仅限于“元素修改”,如若“元素增删”,那两个Hashmap对象就“翻脸不认人”了,不会同步更新。

4、hashmap.clone()

JDK是个难得的学习材料,源码还是要读的。现在也粘贴过来,做一些记录。

/**
* Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
* values themselves are not cloned.
* 【咱们中文叫“深拷贝”,老外美其名曰“拷贝一份实例的'浅拷贝'”,更加严谨】
* @return a shallow copy of this map
*/
@SuppressWarnings("unchecked")
@Override
public Object clone() {
HashMap<K,V> result;
try {
result = (HashMap<K,V>)super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
result.reinitialize();
result.putMapEntries(this, false);
return result;
}
/**
* Implements Map.putAll and Map constructor
*
* @param m the map
* @param evict false when initially constructing this map, else
* true (relayed to method afterNodeInsertion).
*/
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
if (table == null) { // pre-size
float ft = ((float)s / loadFactor) + 1.0F;
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
if (t > threshold)
threshold = tableSizeFor(t);
}
else if (s > threshold)
resize();
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
//【putVal方法里面我初步扫了一下,也未涉及Hashmap instance对象的新建,是一些Hashmap结构中的Node的新建】
putVal(hash(key), key, value, false, evict);
}
}
}

以代码最终解释权由JDK1.8.x所有。

关于Java中的HashMap的深浅拷贝的测试与几点思考的更多相关文章

  1. 沉淀再出发:java中的HashMap、ConcurrentHashMap和Hashtable的认识

    沉淀再出发:java中的HashMap.ConcurrentHashMap和Hashtable的认识 一.前言 很多知识在学习或者使用了之后总是会忘记的,但是如果把这些只是背后的原理理解了,并且记忆下 ...

  2. java 中遍历hashmap 和hashset 的方法

    一.java中遍历hashmap:    for (Map.Entry<String, Integer> entry : tempMap.entrySet()) {     String ...

  3. Java中关于HashMap的元素遍历的顺序问题

    Java中关于HashMap的元素遍历的顺序问题 今天在使用如下的方式遍历HashMap里面的元素时 1 for (Entry<String, String> entry : hashMa ...

  4. Java中关于HashMap的使用和遍历(转)

    Java中关于HashMap的使用和遍历 分类: 算法与数据结构2011-10-19 10:53 5345人阅读 评论(0) 收藏 举报 hashmapjavastringobjectiterator ...

  5. [转]为什么Java中的HashMap默认加载因子是0.75

    前几天在一个群里看到有人讨论hashmap中的加载因子为什么是默认0.75. HashMap源码中的加载因子 static final float DEFAULT_LOAD_FACTOR = 0.75 ...

  6. Java中的HashMap的工作原理是什么?

    问答题23 /120 Java中的HashMap的工作原理是什么? 参考答案 Java中的HashMap是以键值对(key-value)的形式存储元素的.HashMap需要一个hash函数,它使用ha ...

  7. JAVA中JavaBean对象之间属性拷贝的方法

    JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,对于这种情况,可以采用以下几个简便方法处理. 下面对这 ...

  8. Java中的阻塞和非阻塞IO包各自的优劣思考(经典)

    Java中的阻塞和非阻塞IO包各自的优劣思考 NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式. 反应器(Reactor):用于事件多路分离和分派的体系结构模式 通常的,对一个 ...

  9. hash表及Java中的HashMap与HashSet

    链接: http://alex09.iteye.com/blog/539545/ 当程序试图将一个 key-value 对放入 HashMap 中时,程序首先根据该 key 的 hashCode() ...

随机推荐

  1. 10秒钟sublime text 3安装SVN插件

    注意:此处我提前已经安装了towerSVN,你可能需要提前安装好 towerSVN,之前安装redis之后我才明白,安装插件时安装软件好像 是一个必要的步骤,也就是说安装插件只是让你能在这里使用你已 ...

  2. 用PHP实现Windows域验证

    系统集成中,可能会有这种需求 Windows 域验证本质上是LDAP验证 但在网上居然找不到详细的技术文档,可见不受待见之极.

  3. PING的原理以及ICMP协议

    主要内容: 1.ping的原理以及工作过程 2.ICMP协议 3.ICMP的应用:ping,traceroute 1.ping的原理以及工作过程  ping的原理  ping 程序是用来探测主机到主机 ...

  4. Java线程池的工作原理与实现

    简单介绍 创建线程有两种方式:继承Thread或实现Runnable.Thread实现了Runnable接口,提供了一个空的run()方法,所以不论是继承Thread还是实现Runnable,都要有自 ...

  5. OGEngine_2.x中BitmapFont加载后黑屏问题的解决办法

    在我使用OGEngine_2.x进行消灭圈圈(星星)游戏的实践的时候,使用BitmapFont对自定义字体进行调用. 原文字体教程如下:http://blog.csdn.net/OrangeGame/ ...

  6. ANT不完全总结,包含各种命令,ant例子等,转自:http://lavasoft.blog.51cto.com/62575/87306

    ANT不完全总结   好久没有用Ant了,最近让MyEclipse.JBuilder2008逼的重回Ant上了.手生了,写了一个脚本后,重新总结下.参考了官方的文档和网上一些资料.   一.ANT的介 ...

  7. Py福利,基于uiautomatorviewer 的Python 自动化代码自动生成工具分享(jar已发布GitHub,欢迎Star)

    前言做UI自动化无论你用SDK自带的uiautomatorviewer还是Macaca还是Appium自动的inspector,代码最多的就是那些繁琐重复的找元素后点击,输入,长按.....等.现在偷 ...

  8. Python_程序实现发红包

    发红包 200块钱  20个红包 将200块随机分成20份 基础版本: import random ret = random.sample(range(1, 200 * 100), 19) ret = ...

  9. Numpy 通用函数

    frompyfunc的调用格式为frompyfunc(func, nin, nout),其中func是计算单个元素的函数,nin是此函数的输入参数的个数,nout是此函数的返回值的个数 # 注:用fr ...

  10. IDC 知识库

    http://www.51idc.com/help/supportHelp.html Host key verification failed解决IIS错误信息--另一个程序正在使用此文件,进程无法访 ...