先申明复制速度结果

  1. System.arraycopy()
  2. clone()
  3. Arrays.copyof()
  4. for()

背后原理探究

首先要申明的是这4种方法中的前3种是没有本质区别的,对象都是浅复制(复制地址),而普通类型都是深复制(复制值),简单来说

浅复制:复制地址,相当于复制了房子(内存数据)的钥匙,一改全改

深复制:复制值,通俗意义上的拷贝,相当于建了一个一模一样的房子(内存的数据)


接下来说说3种方式:

System.arraycopy()

源码如下:@HotSpotIntrinsicCandidatepublic static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

可以看到这是一个native(本地)方法,也就是说是用C++写的,所以其效率比非native方法更高

但更要注意的是上面的注解@HotSpotIntrinsicCandidate,我们来看官方对这个注解的解释

* The {@code @HotSpotIntrinsicCandidate} annotation is specific to the
 * HotSpot Virtual Machine. It indicates that an annotated method
 * may be (but is not guaranteed to be) intrinsified by the HotSpot VM. A method
 * is intrinsified if the HotSpot VM replaces the annotated method with hand-written
 * assembly and/or hand-written compiler IR
-- a compiler intrinsic -- to improve
 * performance.
The {@code @HotSpotIntrinsicCandidate} annotation is internal to the
 * Java libraries and is therefore not supposed to have any relevance for application
 * code.

注意红字粗体所说,为了提升性能,在JVM里对该注解的进行了手写,这里要提一个叫JNI(Java Native Interface)的东西,普通的native方法通俗的讲就是编译后还要通过JNI再次编译成.cpp文件才能执行.而有 @HotSpotIntrinsicCandidate这个注解的方法在JVM里就是用.cpp文件写好的,所以就跳过了JNI阶段,所以速度就能提升,这也是System.arraycopy()速度冠绝群雄的原因.


Object.clone()

源码如下:@HotSpotIntrinsicCandidateprotected native Object clone() throws CloneNotSupportedException;

可以看到它也是native方法,也有@HotSpotIntrinsicCandidate注解,那为啥速度比上面的大哥慢呢?这就要看到官方解释的一句

It indicates that an annotated method may be (but is not guaranteed to be) intrinsified by the HotSpot VM

注意用词:may be (but is not guaranteed to be),是的,clone()方法就是悲催的but,它并没有被手工写在JVM里面,所以它不得不走JNI的路子,所以它就成了2哥。


Arrays.copyof()

 源码如下 @HotSpotIntrinsicCandidatepublic static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}

3弟也有注解 @HotSpotIntrinsicCandidate,但它甚至不是native方法,所以这个注解也就是混子,也更印证了2哥的待遇,

而且可以很明显的看到里面本质是调用了大哥  System.arraycopy()来实现的,所以效率垫底也是妥妥的。

for()

这个就可以退出群聊吧!for()无论是基本数据类型还是引用数据类型统统是深复制,而且其也不是封装的函数,所以退出群聊妥妥的。


最后上测试代码,有兴趣的可以看看:

package 问题;import java.util.Arrays;public class CopySpeed implements Cloneable {/** * 数组复制速度 1.System.arraycopy() 2.clone() 3.Arrays.copyof() 4.for()* * * */int i = 0;String value = "123";/** 基本数据类型测试* * */public long[] CopySpeedTest(int[] t) {/** 初始化所有* */int length = t.length;int[] systemCopy = new int[t.length];int[] clone = new int[t.length];int[] arraysCopyOf = new int[t.length];int[] For = new int[t.length];/** 执行复制操作,并统计时间* */long begin = System.currentTimeMillis();System.arraycopy(t, 0, systemCopy, 0, t.length);long end = System.currentTimeMillis();long arraycopyTimes = end - begin;begin = System.currentTimeMillis();clone = t.clone();end = System.currentTimeMillis();long cloneTimes = end - begin;begin = System.currentTimeMillis();arraysCopyOf = Arrays.copyOf(t, t.length);end = System.currentTimeMillis();long arraysCopyOfTimes = end - begin;/** 为了方便查看,这里设定下面程序只执行一次* */if (i == 0) {/** 查看哈希值*/System.out.println("t:\t" + t.hashCode());System.out.println("systemCopy:\t" + systemCopy.hashCode());System.out.println("clone:\t" + clone.hashCode());System.out.println("arraysCopyOf:\t" + arraysCopyOf.hashCode());i++;}/** 运行时间统计* */long[] times = new long[3];times[0] = arraycopyTimes;times[1] = cloneTimes;times[2] = arraysCopyOfTimes;return times;}/** * 引用数据类型结果* * */public long[] CopySpeedTest(CopySpeed[] t) {/** 初始化所有* */int length = t.length;CopySpeed[] systemCopy = new CopySpeed[length];CopySpeed[] clone = new CopySpeed[length];CopySpeed[] arraysCopyOf = new CopySpeed[length];/** 执行复制操作,并统计时间* */long begin = System.currentTimeMillis();System.arraycopy(t, 0, systemCopy, 0, t.length);long end = System.currentTimeMillis();long arraycopyTimes = end - begin;begin = System.currentTimeMillis();clone = t.clone();end = System.currentTimeMillis();long cloneTimes = end - begin;begin = System.currentTimeMillis();arraysCopyOf = Arrays.copyOf(t, t.length);end = System.currentTimeMillis();long arraysCopyOfTimes = end - begin;/** 为了方便查看,这里设定下面程序只执行一次* */if (i == 1) {/** 查看哈希值*/System.out.println("t[0]:\t" + t[0].hashCode());System.out.println("systemCopy[0]:\t" + systemCopy[0].hashCode());System.out.println("clone[0]:\t" + clone[0].hashCode());System.out.println("arraysCopyOf[0]:\t" + arraysCopyOf[0].hashCode());/** 修改新对象的值来判断是浅复制还是深复制* */System.out.println("深浅复制判断,以value属性判断");System.out.println("修改前t[0]:\t" + t[0].value);System.out.println("修改前systemCopy[0]:\t" + systemCopy[0].value);System.out.println("修改前clone[0]:\t" + clone[0].value);System.out.println("修改前arraysCopyOf[0]:\t" + arraysCopyOf[0].value);System.out.println("---------------------------");t[0].value = "t";systemCopy[0].value = "systemCopy";clone[0].value = "clone";arraysCopyOf[0].value = "arraysCopyOf";System.out.println("修改后t[0]:\t" + t[0].value);System.out.println("修改后systemCopy[0]:\t" + systemCopy[0].value);System.out.println("修改后clone[0]:\t" + clone[0].value);System.out.println("修改后arraysCopyOf[0]:\t" + arraysCopyOf[0].value);i++;}/** 运行时间统计*/long[] times = new long[3];times[0] = arraycopyTimes;times[1] = cloneTimes;times[2] = arraysCopyOfTimes;return times;}public static void main(String args[]) {CopySpeed speed = new CopySpeed();System.out.println("基本类型");long[] baseTimes = new long[] { 0, 0, 0 };int[] baseArrays = new int[10000000];for (int i = 0; i < baseArrays.length; i++) {baseArrays[i] = i;}for (int i = 0; i < 20; i++) {// System.out.print(i+"次");long[] temp = speed.CopySpeedTest(baseArrays);baseTimes[0] += temp[0];baseTimes[1] += temp[2];baseTimes[2] += temp[1];// System.out.println();}baseTimes[0] /= 20;baseTimes[1] /= 20;baseTimes[2] /= 20;System.out.println(Arrays.toString(baseTimes));System.out.println("引用类型");long[] ObjectTimes = new long[] { 0, 0, 0 };CopySpeed[] ObjectArrays = new CopySpeed[10000000];for (int i = 0; i < ObjectArrays.length; i++) {ObjectArrays[i] = new CopySpeed();}for (int i = 0; i < 20; i++) {// System.out.print(i+"次");long[] temp = speed.CopySpeedTest(ObjectArrays);ObjectTimes[0] += temp[0];ObjectTimes[1] += temp[1];ObjectTimes[2] += temp[2];// System.out.println();}ObjectTimes[0] /= 20;ObjectTimes[1] /= 20;ObjectTimes[2] /= 20;System.out.println(Arrays.toString(ObjectTimes));}}

结果:

基本类型
t:  1552787810
systemCopy: 1361960727
clone:  739498517
arraysCopyOf:   125130493
[10, 14, 15]
引用类型
t[0]:   166239592
systemCopy[0]:  166239592
clone[0]:   166239592
arraysCopyOf[0]:    166239592
深浅复制判断,以value属性判断
修改前t[0]:    123
修改前systemCopy[0]:   123
修改前clone[0]:    123
修改前arraysCopyOf[0]: 123
---------------------------
修改后t[0]:    t
修改后systemCopy[0]:   t
修改后clone[0]:    t
修改后arraysCopyOf[0]: t
[22, 31, 55]

结果分析:

基本类型
t:  1552787810
systemCopy: 1361960727
clone:  739498517
arraysCopyOf:   125130493
[10, 14, 15]对于基本数据类型可以看到4个对象的hashcode完全不同,也就验证了前面的深复制的猜想而10,14,15的运行时间也能证明他们的效率差别,当然因为是基本数据类型,
而且数据量不算恐怖,所以差距并不大,特别是clone和arraysCopyOf
可以明显的看到,clone因为JNI的耽误,而Arrays.CopyOf因为System.Copy的加成速度也不赖。引用类型
t[0]:   166239592
systemCopy[0]:  166239592
clone[0]:   166239592
arraysCopyOf[0]:    166239592对于引用类型,额可以看到4个对象的hashcode值完全相同,说明指向的是同一块内存深浅复制判断,以value属性判断
修改前t[0]:    123
修改前systemCopy[0]:   123
修改前clone[0]:    123
修改前arraysCopyOf[0]: 123
---------------------------
修改后t[0]:    t
修改后systemCopy[0]:   t
修改后clone[0]:    t
修改后arraysCopyOf[0]: t
[22, 31, 55]这里以对象的属性value做测试,可以看到t[0]里面的数据更改后,所有的数据都更改了,说明3种方法对于对象都是浅复制

数组复制速度 System.arraycopy()clone() Arrays.copyof() for()探究相关推荐

  1. System.arraycopy和Arrays.copyOf的原理解剖

    数组的复制其实在很多业务情况下会用到,不同的业务情况下选择适合的方式来实施复制是每个开发人员要考虑的事情. 那么System.arraycopy.Arrays.copyOf到底是如何复制的呢?接下来就 ...

  2. System.arraycopy 和Arrays.copyOf

    1.Arrays.copyOf()的实现是用的是System.arrayCopy(); 2.System.arrayCopy()需要目标数组,对两个数组的内容进行可能不完全的合并操作. 3.Array ...

  3. System.arraycopy()和 Arrays.copyOf()的区别联系(源码深度解析copyOf扩容原理)

    1.System.arraycopy()方法 public static void arraycopy(Object src, int srcPos, Object dest, int destPos ...

  4. java arraycopyof_Java中System.arraycopy()和Arrays.copyOf()的区别

    System.arraycopy() 这是一个由java标准库提供的方法.用它进行复制数组比用for循环要快的多. arraycopy()需要的参数有:源数组,从源数组中的什么位置开始复制的偏移量,目 ...

  5. 再谈System.arraycopy和Arrays.copyOf

    之前转载过一篇博文,介绍过这两个方法,今天想要再次详细的了解一下. public static native void arraycopy(Object src, int srcPos,Object ...

  6. System.arraycopy和Arrays.copyOf的关系

    参考连接: https://www.cnblogs.com/happyxiaoyu/p/5786971.html https://blog.csdn.net/expect521/article/det ...

  7. java字符串数组拷贝函数_java 数组的拷贝 对象数组的拷贝 System.arraycopy函数

    /* java 数组的操作   System类的arraycopy静态函数用于数组拷贝   数组是不能越界的 对象数组的复制实际上是复制的引用的拷贝  也就是对象的地址 */ class Point ...

  8. java 数组的拷贝 对象数组的拷贝 System.arraycopy函数

    /* java 数组的操作   System类的arraycopy静态函数用于数组拷贝   数组是不能越界的 对象数组的复制实际上是复制的引用的拷贝  也就是对象的地址  */ class Point ...

  9. byte数组快速拷贝,byte数组合并,System.arraycopy详解

    博客来源: 项目过程中用到byte[]数组相加问题,给出两个byte[] 需要合并成一个byte[]进行计算-那么需求来了--数据量达10W级,怎么合并 调用系统自带方法(System.arrayco ...

最新文章

  1. mysql 服务启动异常
  2. 被忽视的 Application
  3. mysql insert报错_mysql数据库使用insert语句插入中文数据报错
  4. 一个类型初始值设定项引发异常
  5. 第十章 优先级队列 (b1)完全二叉堆:结构
  6. hdu 3401(单调队列优化dp)
  7. 主成分分析(PCA)算法,K-L变换 角度
  8. 单列(写了池子pool)用list实现的方法, 与伪单例(写了池子zidianpool),用字典实现的方法,可以存入不同,i名字的物体...
  9. Linux学习之旅(二)Linux文档操作
  10. python GUI初步
  11. 王道考研机试指南重写
  12. python制作简单动画_如何使用python制作简单的动画?
  13. 你利用好网络这个工具了吗?
  14. 使用手持式频谱分析仪进行TDD信号分析
  15. 浅释丹道筑基功―—―混元桩【转载】
  16. 基于神经网络的目标检测论文之结尾:总结与展望
  17. R语言ggplot2可视化在轴标签中添加上标(Superscript)和下标(subscript)实战
  18. 成都启英泰伦科技有限公司
  19. Android中解析读取复杂word,excel,ppt等的方法
  20. 深度学习系列37:CLIP模型

热门文章

  1. c#winform演练 ktv项目 实现上一曲和下一曲的播放功能
  2. django-QueryDict对象
  3. 查看SQL Server当前会话的隔离级别
  4. Fedora/Redhat 在线安装更新软件包,yum 篇 ── 给新手指南 (转载)
  5. 【2018.05.04学习笔记】【linux基础知识10.1-10.5】
  6. ThinkPHP3.2 下载、导入、导出功能的设计与实现
  7. 关于docker部署javaweb应用的问题
  8. SwarmKit知多少——来自源码世界的深入解读
  9. Facebook想用机器人取代App
  10. javascript将base64编码的图片数据转换为file并提交