热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javaarraylist深拷贝_Java中如何克隆集合——ArrayList和HashSet深拷贝

编程人员常常误用各个集合类提供的拷贝构造函数做为克隆List,Set,ArrayList,HashSet或者其余集合实现的方法。须要记住的

编程人员常常误用各个集合类提供的拷贝构造函数做为克隆List,Set,ArrayList,HashSet或者其余集合实现的方法。须要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味着存储在原始List和克隆List中的对象是相同的,指向Java堆内存中相同的位置。增长了这个误解的缘由之一是对于不可变对象集合的浅克隆。因为不可变性,即便两个集合指向相同的对象是能够的。字符串池包含的字符串就是这种状况,更改一个不会影响到另外一个。使用ArrayList的拷贝构造函数建立雇员List的拷贝时就会出现问题,Employee类不是不可变的。在这种状况下,若是原始集合修改了雇员信息,这个变化也将反映到克隆集合。一样若是克隆集合雇员信息发生变化,原始集合也会被更改。绝大多数状况下,这种变化不是咱们所但愿的,克隆对象应该与原始对象独立。解决这个问题的方法是深克隆集合,深克隆将递归克隆对象直到基本数据类型或者不可变类。本文将了解一下深拷贝ArrayList或者HashSet等集合类的一种方法。若是你了解深拷贝与浅拷贝之间的区别,那么理解集合深克隆的方法就会很简单。html

Java集合的深克隆

下面例子有一个Employee集合,Employee是可变对象,成员变量name和designation。它们存储在HashSet中。使用java.util.Collection接口的addAll()方法建立集合拷贝。而后修改存储在原始集合每一个Employee对象的designation值。理想状况下这个改变不会影响克隆集合,由于克隆集合和原始集合应该相互独立,可是克隆集合也被改变了。修正这个问题的方法是对存储在Collection类中的元素深克隆。java

package javaBasic;

import java.util.Collection;

import java.util.HashSet;

import java.util.Iterator;

/**

* Java program to demonstrate copy constructor of Collection provides shallow

* copy and techniques to deep clone Collection by iterating over them.

*

* @author http://javarevisited.blogspot.com

*/

public class CollectionCloningTest {

public static void main(String args[]) {

// deep cloning Collection in Java

Collection org = new HashSet();

org.add(new Employee("Joe", "Manager"));

org.add(new Employee("Tim", "Developer"));

org.add(new Employee("Frank", "Developer"));

// creating copy of Collection using copy constructor

Collection copy = new HashSet(org);

System.out.println("Original Collection {} " + org);

System.out.println("Copy of Collection {} " + copy);

Iterator itr = org.iterator();

while (itr.hasNext()) {

itr.next().setDesignation("staff");

}

System.out.println("Original Collection after modification {} " + org);

System.out

.println("Copy of Collection without modification {} " + copy);

// deep Cloning List in Java

}

}

class Employee {

private String name;

private String designation;

public Employee(String name, String designation) {

this.name = name;

this.designation = designation;

}

public String getDesignation() {

return designation;

}

public void setDesignation(String designation) {

this.designation = designation;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return String.format("%s: %s", name, designation);

}

}

输出:编程

能够看到改变原始Collection中Employee对象(改变designation为”staff“)在克隆集合中也有所反映,由于克隆是浅拷贝,指向堆中相同的Employee对象。为了修正这个问题,须要遍历集合,深克隆Employee对象,在这以前,要重写Employee对象的clone方法。app

1)Employee实现Cloneable接口

2)为Employee类增长下面的clone()方法ide

3)不使用拷贝构造函数,使用下面的代码来深拷贝集合函数

Codethis

package javaBasic;

import java.util.Collection;

import java.util.HashSet;

import java.util.Iterator;

/**

* Java program to demonstrate copy constructor of Collection provides shallow

* copy and techniques to deep clone Collection by iterating over them.

*

* @author http://javarevisited.blogspot.com

*/

public class CollectionCloningTest {

public static void main(String args[]) {

// deep cloning Collection in Java

Collection org = new HashSet();

org.add(new Employee("Joe", "Manager"));

org.add(new Employee("Tim", "Developer"));

org.add(new Employee("Frank", "Developer"));

// creating copy of Collection using copy constructor

// Collection copy = new HashSet(org);

/**

* 不使用拷贝构造函数,使用下面的代码来深拷贝集合

*/

Collection copy = new HashSet(org.size());

Iterator iterator = org.iterator();

while (iterator.hasNext()) {

copy.add(iterator.next().clone());

}

System.out.println("Original Collection {} " + org);

System.out.println("Copy of Collection {} " + copy);

Iterator itr = org.iterator();

while (itr.hasNext()) {

itr.next().setDesignation("staff");

}

System.out.println("Original Collection after modification {} " + org);

System.out

.println("Copy of Collection without modification {} " + copy);

// deep Cloning List in Java

}

}

class Employee implements Cloneable {

private String name;

private String designation;

public Employee(String name, String designation) {

this.name = name;

this.designation = designation;

}

public String getDesignation() {

return designation;

}

public void setDesignation(String designation) {

this.designation = designation;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return String.format("%s: %s", name, designation);

}

@Override

protected Employee clone() {

Employee clone = null;

try {

clone = (Employee) super.clone();

} catch (CloneNotSupportedException e) {

throw new RuntimeException(e); // won't happen

}

return clone;

}

}

4)运行相同的代码更改原始集合,克隆集合不会也被更改。spa

能够看到克隆集合和原始集合相互独立,它们指向不一样的对象。code

d381a461360f4cd8ab8ef3dc.html

这就是Java中如何克隆集合的内容。如今咱们知道拷贝构造函数或者List或Set等各类集合类的addAll()方法仅仅建立了集合的浅拷贝,并且原始集合和克隆集合指向相同的对象。为避免这个问题,应该深克隆集合,遍历集合克隆每一个元素。尽管这要求集合中的对象必须支持深克隆操做。orm



推荐阅读
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
author-avatar
优雅的鼻涕泡
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有