`
wangqisen
  • 浏览: 47101 次
文章分类
社区版块
存档分类
最新评论

关于HashMap的拷贝问题

 
阅读更多

今天在看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;
	}
}

这里的第二个构造函数就是拷贝构造函数。
分享到:
评论

相关推荐

    HashMap.txt

    该文件是拷贝的HashMap源码,在源码之上我对核心的代码都做了完整的注释,相信读者一定能够一看就懂,哈哈,HashMap是面试重灾区,我也是面试时才通读HashMap的。

    HashMap的特点与使用方法详解.docx

    HashMap 的特点: HashMap 的键必须是唯一的,不能重复。 HashMap 的键允许为 null,但只能有一个这样的键;值可以有多个 null。...HashMap 实现了 Cloneable 和 Serializable 接口,因此可以拷贝和序列化。

    Java开发常用的方法

    数组拷贝,建议使用System.arraycopy()速度更快,把source数据内容拷贝到destination中使用Object则支持多种对象数组;去除数组中的重复元素;四舍五入;判断字符串是否是小数;半角数字的unicode范围;取得ascii码;

    微服务架构面试专题系列(MySQL,JVM,并发编程,RabbitMQ消息中间件,Spring)

    说一下 JVM 运行时数据区 深拷贝和浅拷贝 说一下堆栈的区别? 队列和栈是什么?有什么区别? 对象的创建 为对象分配内存 处理并发安全问题 对象的访问定位 2. MySQL包括了:索引,锁,事务等常见考点 MySql的主从...

    10G的Java面试题视频课

    说一下 JVM 运行时数据区 深拷贝和浅拷贝 说一下堆栈的区别? 队列和栈是什么?有什么区别? 对象的创建 为对象分配内存 处理并发安全问题 对象的访问定位 2. MySQL包括了:索引,锁,事务等常见考点 MySql的主从...

    Java程序员大厂面试(进大厂必看)

    说一下 JVM 运行时数据区 深拷贝和浅拷贝 说一下堆栈的区别? 队列和栈是什么?有什么区别? 对象的创建 为对象分配内存 处理并发安全问题 对象的访问定位 2. MySQL包括了:索引,锁,事务等常见考点 MySql的主从...

    互联网企业面试真题.zip

    说一下 JVM 运行时数据区 深拷贝和浅拷贝 说一下堆栈的区别? 队列和栈是什么?有什么区别? 对象的创建 为对象分配内存 处理并发安全问题 对象的访问定位 2. MySQL包括了:索引,锁,事务等常见考点 MySql的主从...

    java-server-interview-questions:java服务端面试题整理

    HashMap的并发问题 了解LinkedHashMap的应用吗 反射的原理,反射创建类实例的三种方式是什么? cloneable接口实现原理,浅拷贝or深拷贝 Java NIO使用 hashtable和hashmap的区别及实现原理,hashmap会问到数组索引,...

    AVL tree实现源码

    AVL tree的源码实现。该AVL tree为模板容器,可以在其中放入任何东西。被放入的对象需要实现拷贝构造函数与赋值构造函数。该程序能够在linux下面顺利通过编译。平时随意开发,如有不足之处,还请见谅!!!

    Java面试经典题,对JAVA面试很有帮助

    18.深拷贝和浅拷贝的区别是什么 19.final有哪些用法 20.static都有哪些用法 21.3*0.1 == 0.3返回值是什么 22.a=a+b与a+=b有什么区别吗 23.try catch finally,try里有return,finally还执行么 ...

    Java 基础核心总结 +经典算法大全.rar

    BIO 和 NIO 拷贝文件的区别操作系统的零拷贝 选择器(Selectors) 选择键(SelectionKey) 示例:简易的客户端服务器通信 集合 集合框架总览 -、Iterator Iterable ListIterator 二、Map 和 Collection 接口Map 集合体系...

    mybatis学习笔记

    8.3 第三步:拷贝生成的mapper文件到工程中指定的目录中 73 8.3.1 Mapper.xml 73 8.3.2 Mapper.java 73 8.3.3 第四步Mapper接口测试 73 8.4 逆向工程注意事项 74 8.4.1 Mapper文件内容不覆盖而是追加 74 8.4.2 Table...

    Android TagCloudView云标签的使用方法

    这两天做了一个项目,发现标签不能更改任意一个标签的字体的颜色,需求如同置前标签,然后就对tagcloudeview稍做修改做了这么一个... public void setTagsByPosition(HashMap&lt;Integer&gt; positions, List&lt;String&gt; tagList

    java面试大全视频版

    Java面试题11.HashMap和HashTable的区别 Java面试题12.实现一个拷贝文件的工具类要使用字节流还是字符串 Java面试题13.线程的的实现方式?怎么启动线程?怎么区分线程? Java面试题14.线程并发库和线程池的作用 Java...

    史上最全java面试,103项重点知识,带目录

    63. 深拷贝和浅拷贝区别是什么? 28 六、Java Web 28 64. jsp 和 servlet 有什么区别? 28 65. jsp 有哪些内置对象?作用分别是什么? 29 66. 说一下 jsp 的 4 种作用域? 29 67. session 和 cookie 有什么区别? 30...

    leetcode走方格起点到终点-Leetcode:自己刷leetcode的做题记录,意为在此存档备份

    HashMap Q99 : 二分排序树的 中序有序性。 13毫秒 Q130 : 涂色问题:char[][] dfs涂色。 Q133 : 图的深拷贝 Q415 : 字符串数字求和 Q43 : 字符串数字相乘 Q20 : 验证括号是否完全匹配。 Q50 : 快速幂 实现 pow ,...

    Java常见面试题208道.docx

    面试题包括以下十九部分:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    面试题包含了不同技术层面的面试问题,同时也能对一些没有面试开发经验的小白给予不可估量的包装, 让你的薪水绝对翻倍, 本人亲试有效.Java面试题84集、java面试专属及面试必问课程,所有的面试题有视屏讲解, 解答方案....

Global site tag (gtag.js) - Google Analytics