关于HashMap的拷贝问题
来源:互联网 发布:批量修图软件 编辑:程序博客网 时间:2024/05/21 03:55
今天在看hashtable源码时看到clone()函数,官方文档说hashtable实现的是浅拷贝,但是,粗看之下,其的确对每一个Entry都调用了clone函数,怎么会是浅拷贝呢?
如下:
public synchronized Object clone() {try { Hashtable<K,V> t = (Hashtable<K,V>) super.clone(); t.table = new Entry[table.length]; for (int i = table.length ; i-- > 0 ; ) {t.table[i] = (table[i] != null) ? (Entry<K,V>) table[i].clone() : null; } t.keySet = null; t.entrySet = null; t.values = null; t.modCount = 0; return t;} catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError();} }
回过头去看HashMap的clone函数,发现也是实现了对每个Entry本身的clone,如下:
public Object clone() { HashMap<K,V> result = null;try { result = (HashMap<K,V>)super.clone();} catch (CloneNotSupportedException e) { // assert false;} result.table = new Entry[table.length]; result.entrySet = null; result.modCount = 0; result.size = 0; result.init(); result.putAllForCreate(this); return result; }
那么,为什么会是浅拷贝呢?‘
仔细思考了下,并看了Entry的克隆函数,就可以明白,虽然两者均实现了对Entry数组本身的拷贝,但是,对于Entry的键和值,都是使用的简单地浅拷贝,因此,说它是浅拷贝。
Entry中的clone函数代码如下:
protected Object clone() { return new Entry<K,V>(hash, key, value, (next==null ? null : (Entry<K,V>) next.clone()));}
到这里算完了么?那么,为什么源码不实现deep clone,达到使用时的便捷性呢?在思考下,我认为,这是由于范型本身的擦除特性引起的,由于java语言本身范型机制的不强大,使得无法完成在不知道具体类型的情况下,对键和值实现深度拷贝。
到这里算完了么?其实,我实验了HashMap的拷贝功能,代码如下:
public static void main(String args[]){HashMap<Integer,Integer> map1=new HashMap<Integer,Integer>();map1.put(1,2);map1.put(2,3);HashMap<Integer,Integer> map2=(HashMap<Integer,Integer>)map1.clone();map2.put(2,5);System.out.println(map1.get(2));}
结果是会像上面我blabla说的一样,得到的拷贝源的值也会改变呢?No,No,No。实际上,这里是十分特殊的,由于Integer在处理时实际上是要作为基本类型来处理的,所以,你会看到结果其实不会改变。而下面的例子,就是正常的情况下的拷贝函数:
HashMap source = new HashMap(); source.put("key1","value1"); source.put("key2","value2"); for(Iterator keyItr = source.keySet().iterator();keyItr.hasNext();){ Object key = keyItr.next(); System.out.println(key + " : "+source.get(key)); } System.out.println("----------------- 1 ----------------"); Map targetMap = (HashMap)source.clone(); for(Iterator keyItr = targetMap.keySet().iterator();keyItr.hasNext();){ Object key = keyItr.next(); System.out.println(key + " : "+source.get(key)); } System.out.println("---------------- 2 ----------------"); Object aa = targetMap.put("key1","modify key1"); System.out.println("aa = "+aa); for(Iterator keyItr = source.keySet().iterator();keyItr.hasNext();){ Object key = keyItr.next(); System.out.println(key + " : "+source.get(key)); } }
关于拷贝,在拷贝一个类时,如果这个类中有final类型的成员变量,那么由于final类型的成员变量如果没有在声明时赋值,只能在构造函数中赋值,因此,这时就必须使用拷贝构造函数的方法来实现深度拷贝,代码如下:
class Test6_A implements Cloneable{private final int x;public Test6_A(int x){this.x=x;}public Test6_A(Test6_A t){this.x=t.x;}public Test6_A clone(){Test6_A a=new Test6_A(this);return a;}}
这里的第二个构造函数就是拷贝构造函数。
0 0
- 关于HashMap的拷贝问题
- 关于hashmap的遍历问题
- 关于hashmap的遍历问题
- 关于HashMap的使用问题
- 关于hashmap put 的问题
- 关于HashMap的一些问题
- 关于CString的拷贝问题
- Map拷贝 关于对象深拷贝 浅拷贝的问题
- Map拷贝 关于对象深拷贝 浅拷贝的问题
- Map拷贝 关于对象深拷贝 浅拷贝的问题
- Map拷贝 关于对象深拷贝 浅拷贝的问题
- 关于java的HashMap的问题
- 关于拷贝构造函数、字符串拷贝的问题
- 关于数组的复制问题------浅拷贝,深拷贝
- 拷贝构造函数关于指针的拷贝问题
- 关于freemarker里面的hashmap使用问题
- 关于freemarker里面的hashmap使用问题
- 关于hashmap使用迭代器的问题
- IOS 为UILabel添加长按复制功能
- C++诤言
- sql server强行断开连接
- PL/SQL (关于oracle学习总结的说明)
- IT:从上网开始
- 关于HashMap的拷贝问题
- oracle用户密码过期以及解雇(expired)的处理
- SSH和SpringMVC
- (转)Linux网络编程(3):信号处理与定时机制简要学习
- matlab编程与工程应用(第二版) 第八章 元胞数组 笔记
- weka下运行libsvm的方法
- windows如何使用ssh登录ubuntu
- 软件文档编写向导
- Oracle Data Guard 环境配置