`
mrliang
  • 浏览: 2609 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

java 6 中的数组复制

阅读更多
  Java语言包含了一些精彩的“古董”。例如仍然不支持在switch语句中使用String对象。(不过已经更新为可以支持enum类型了) 。这个理由似乎可以追溯到switch语句是源自于c语言。不论如何,在switch语句中不能使用string对象进行判断对我来说都是很不方便的。
  System.arraycopy, 快速拷贝数组内容到另一数组的方法,似乎也有类似的传统。方法名称看上去像一个旧风格的C函数memcpy,这意味着Java的数组复制方法从第一个版本以来就没有改变.
  arraycopy这个方法是一个系统级别的静态方法,具备很强大的功能,通常的写法如下:
  System.arraycopy(sourceArray, sourceStartIndex, targetArray, targetStartIndex, length);
  该arraycopy方法不仅仅是支持复制到目标数组的全部内容,此外,arraycopy允许设置源和目标的起始索引以及长度来进行内容元素的拷贝。这种额外的灵活性是很有用的,尽管它可能不是我在通常情况下所需要的。例如ArrayList类在插入一个元素时就是用arraycopy来转移数组的内容,这个方法执行得非常快: 在底层不是Java实现的,而是JVM调用的本地方法来实现。
  大多情况下,我需要复制整个数组而不是子集。 我也不需要频繁的转变数组中的元素。 我的System.arrayCopy调用大多需要两行代码:
      String[] source = { "alpha", "beta", "gamma" };
      String[] target = new String[source.length];
      System.arraycopy(source, 0, target, 0, source.length);
更进一步,出于重用性的需要,需要多一点儿的Java代码,如下:
private final <T> T[] copy(T[] source) {
   T[] target = new T[source.length]; // This will not compile!
     System.arraycopy(source, 0, target, 0, source.length);
     return target;
   }
好的,这段代码并不能真正的工作,编译会出错:
Cannot create a generic array of T
通过反射可以解决这个编译问题,下面是可以正确编译的代码:
private final <T> T[] copy(T[] source) {
   Class type = source.getClass().getComponentType();
   T[] target = (T[])Array.newInstance(type, source.length);
   System.arraycopy(source, 0, target, 0, source.length);
   return target;
}
Java编译器会显示一个警告“Type safety: the case from Object to T[] is actually checking against the erased type Object[]” 使用反射意味着没有足够的信息告诉编译器这是否是一个错误的cast,但这确实是一个快速的能够绕过那个讨厌的警告的方法。
@SuppressWarnings("unchecked")
private final <T> T[] copy(T[] source) {
   Class type = source.getClass().getComponentType();
   T[] target = (T[])Array.newInstance(type, source.length);
   System.arraycopy(source, 0, target, 0, source.length);
   return target;
}
包装了这个copy方法,我的客户端代码就很简单了,如下:
String[] source = { "alpha", "beta", "gamma" };
String[] target = copy(source);
好了,我已经快速建立了自己的通用拷贝方法。

copyof的介绍
在Java 6中,我不再需要推出自己的实用方法:Sun公司推出了复制一个数组的直接支持:copyof, 基本使用方法如下:
targetArray = Arrays.copyOf(sourceArray, length);
我写了几个JUnit的测试,以证明copyOf法(及其变种)。 这里的第一个测试,显示其基本功能:
@Test
public void genericArrayCopyOf() {
   Number[] source = { new Double(5.0), new Double(10.0) };
   Number[] target = Arrays.copyOf(source, source.length);
   assertEquals(source, target);
}
JUnit4的一个不错的新特点是它能够使用assertEquals比较两个数组。首先比较JUnit的每个数组的长度,如果两个数组的长度相同,jUnit再比较数组的每个元素中是否相等,如果数组不同,JUnit则提供了一个失败的消息,并显示了不一致的值。
Java重载copyOf以支持原始类型,以及扩展使用。下一项测试显示了这一点:
@Test
public void copyOfWithRange() {
   String[] source = { "0", "1", "2", "3", "4" };
   String[] target = Arrays.copyOfRange(source, 2, 4);
   assertEquals(new String[] { "2", "3" }, target);
}
这是一个数组复制原始使用的测试
@Test
public void primitives() {
   int[] source = { 0, 1, 2, 3, 4 };
   int[] target = Arrays.copyOfRange(source, 4, 5);
   assertEqualsPrim(new int[] { 4 }, target);
}
我写的方法assertEqualsPrim因为JUnit 4不比较两个数组中包含的原始对象。它仅比较两个数组对象的版本。 使用assertEquals比较两个数组意味着Java进行内存地址比较。不过没关系,assertEqualsPrim是很容易写的:
static void assertEqualsPrim(int[] expected, int[] actual) {
   if (expected.length != actual.length)
      fail(String.format("expected length = %s, actual length = %s",
            expected.length, actual.length));
   for (int i = 0; i < expected.length; i++) {
      if (expected[i] != actual[i])
         fail(String.format(
               "mismatch at index %d: expected [%s] but was [%s]", i,
               expected[i], actual[i]));
   }
如果我想通过强制转换返回结果的方式来进行数组拷贝,就会出现下面的测试失败:
@Test
public void genericArrayCopyOfWithNewType() {
   Number[] source = { new Double(5.0), new Double(10.0) };
   Double[] target = (Double[])Arrays.copyOf(source, source.length);
   assertEquals(source, target); // fail!
}
好在java 6中可以通过声明新类型的方式进行数组拷贝
@Test
public void genericArrayCopyOfWithNewType() {
   Number[] source = { new Double(5.0), new Double(10.0) };
   Double[] target = Arrays.copyOf(source, source.length, Double[].class);
   assertEquals(source, target);
}

性能以及替代方案

其实我可以使用Clone方法实现数组复制,所以技术上copyOf是没有必要的。不过,我匆匆写的一个性能测试表明,克隆是相当缓慢。他们还表明,copyOf比arraycopy还慢。所以我将使用新的copyOf方法。

广告时间:轻松阅读尽在阅读地带
分享到:
评论

相关推荐

    java数组复制函数的使用demo

    java学习中数组复制函数的调用方法,供java初学者入门参考使用,分享给大家

    22.java数组的复制.zip

    22.java数组的复制.zip22.java数组的复制.zip22.java数组的复制.zip22.java数组的复制.zip22.java数组的复制.zip22.java数组的复制.zip22.java数组的复制.zip22.java数组的复制.zip22.java数组的复制.zip22.java数组...

    Java数组+数组排序+数组复制+最大最小值+合并数组+数组升降序排序+数组查找

    Java数组: Java数组排序:冒泡排序、选择排序 、插入排序 、快速排序、希尔排序...三种Java数组复制方法 Java数组最大最小值 四种合并Java数组方法 Java数组升降序排序 Java数组查找:二分查找、顺序查找、插值查找法

    07-Java基础(数组-常见问题)

    - 数组复制:可以使用System.arraycopy()方法或者遍历数组进行复制。 - 排序:使用Arrays.sort()方法对数组进行排序,适用于基本类型的数组;对于对象数组,需要自定义比较器。 - 查找:线性查找效率较低,而二分...

    Java中使用数组完成学生成绩统计的多种实现代码清单.pdf

    在Java编程语言中,数组是一种基础且重要的数据结构,用于存储同类型的...以上就是利用Java数组进行学生成绩统计的两种实现方式及其涉及的关键知识点。这些基本技巧是Java编程的基础,适用于各种数据统计和处理场景。

    02-Java基础(数组-常见操作-遍历

    本教程“02-Java基础(数组-常见操作-遍历)”将深入讲解Java数组的概念、创建、初始化以及如何进行遍历等核心知识点。 首先,数组是存储同一类型元素的固定大小的集合。在Java中,数组的声明语法如下: ```java 数据...

    Java数组练习题(带答案).doc

    Java数组是Java编程语言中的基本数据结构之一,用于存储固定数量的同类型元素。了解和熟练掌握数组的使用是学习Java的重要环节。本篇练习题涵盖了数组的基本概念、操作和异常处理,下面是针对题目中涉及知识点的详细...

    java高端技术课程--Java数组如何实现复制

    数组复制是编程中常见的操作,特别是在处理数据时需要备份或移动数据的场景。本篇文章将深入探讨Java中数组的复制方法及其相关知识点。 1. **浅拷贝与深拷贝** 在Java中,数组的复制分为浅拷贝和深拷贝两种。浅...

    java 数组的合并

    在Java编程语言中,数组是一种基础且重要的数据结构,用于存储同类型的元素序列。当我们需要将两个或多个数组合并成一个大的数组时,就需要用到数组的合并技术。本篇文章将详细探讨Java中如何实现数组的合并。 首先...

    Java中数组的各种应用

    在Java编程语言中,数组是一种基础且重要的数据结构,它允许程序员存储同类型的多个元素。本文将深入探讨Java中数组的各种应用,旨在帮助初学者理解并掌握数组的使用。 一、数组定义与初始化 在Java中,数组可以...

    java数组_java_java数组_

    Java数组是Java编程语言中的基本数据结构之一,它允许我们存储多个同类型的元素在一个单一的变量中。数组的使用在程序设计中至关重要,因为它提供了一种高效、有序的方式来管理和访问数据。下面将深入探讨Java数组的...

    Java数组,Java数组,多线程编程

    Java数组是程序设计中的基本构建块,它允许程序员存储多个相同类型的数据在一个单一的结构中。在Java中,数组是一种对象,它们具有固定的大小,并且一旦创建,就不能更改其长度。数组提供了通过索引来访问其元素的...

    03-Java基础(数组-内存空间的划分

    3. **数组复制**:Arrays类提供了copyOf()和copyOfRange()方法进行数组复制。 4. **排序**:Arrays类的sort()方法可以对数组进行排序。 5. **动态扩展**:Java中没有直接的动态扩展数组的操作,但可以通过创建新数组...

    Java中的数组复制(clone与arraycopy)代码详解

    Java中的数组复制(clone与arraycopy)代码详解 Java中的数组复制是通过clone和arraycopy两个方法来实现的。clone方法是Object类的protected方法,用于创建对象的副本,而arraycopy是System类的静态方法,用于将一...

    java 动态的数组链表

    在Java编程语言中,动态数组链表是一种常见的数据结构,它结合了数组和链表的特点,既能快速访问数组中的元素,又能方便地进行插入和删除操作。本文将深入探讨Java中实现动态数组链表的关键概念、操作以及其实现方式...

    5-Java数组与方法

    在Java编程语言中,数组是一种特殊的数据结构,用于存储同类型元素的集合。它们提供了一种方式来组织和管理大量数据,使得我们可以高效地访问和操作这些数据。本章将深入探讨数组的基本概念、定义以及如何在实际编程...

    Java的数组.docx

    在这个文档中,主要涉及了Java数组的声明、创建、初始化、赋值、输出、累加和计算、最大值查找以及冒泡排序等核心概念。 1. **数组的声明与创建**: - `int[] arr;` 这是声明一个整型数组的例子。 - `int[] arr =...

    java 一维数组的创建与使用

    在Java编程语言中,一维数组是数据结构的基础,它允许我们存储同类型的数据集合。本文将深入探讨Java一维数组的创建、初始化、访问以及使用的一些关键知识点。 首先,让我们了解什么是数组。数组是一种线性数据结构...

    用Java动态数组扩充实现线性表

    6. **效率分析**:插入和删除操作在大多数情况下需要O(n)的时间复杂度,因为可能需要复制数组中的所有元素。但在平均情况下,由于扩容和缩容的策略,插入和删除的平均时间复杂度可以接近O(1)。 在提供的代码文件中...

    浅谈Java中复制数组的方式

    Java中复制数组的方式 在 Java 编程语言中,复制数组是一个常见的问题。特别是在数组处理中,需要将一个数组的内容复制到另一个数组中。在 Java 中,可以使用不同的方法来复制数组,本文将详细介绍 Java 中复制数组...

Global site tag (gtag.js) - Google Analytics