前言
java 数组定义和 C 语言中有些区别, Arrays
类提供了一些工具方法,本文总结了copyOf()
、asList()
使用过程中的一些注意点。
本文链接 http://www.alijava.com/array-copy/ 转载请注明出处
数组基础
定义数组
1 2
| int[] a1 = { 1, 2, 3 }; int a1[] = { 1, 2, 3 };
|
int[] a1
把[]
写在前面,更强调类型信息:数组int[]
int[]
也是继承了Object
类, 而不是 Object[]
数组可以创建时赋值,或者创建后再赋值
1 2 3 4 5 6 7 8
| int[] a2 = new int[] { 1, 2, 3 }; int a3[] = new int[] { 1, 2, 3 }; int[] a4 = new int[3]; for (int i = 0; i< a4.length; i++) a4[i] = i;
|
数组长度是 length
,而字符串String
获取长度是length()
foreach 循环
JDK 5.0 引进了被称为foreach
循环来遍历数组
1 2
| for(int element: a4) System.out.println(element);
|
输出
数组作为方法的参数
如果方法的参数是 int[]
- 一是将变量传进去
- 二是匿名格式
new int[] { 1, 2, 3 }
, 传{ 1, 2, 3 }
是错误的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void main(String[] args) { testArr(new int[] { 1, 2, 3 }); } public static void testArr(int[] nums) { for (int element : nums) System.out.println(element); }
|
输出
对于可变长参数的方法
1 2 3 4
| public static void testVariPara(int... nums) { for (int element : nums) System.out.println(element); }
|
下面这两种传递参数方法都可以正常运行
1 2
| testVariPara(new int[] { 1, 2, 3 }); testVariPara(1, 2, 3);
|
Arrays 工具类
toString
Java 没有覆盖(override
) 数组int[]
的toString()方法, 所以
1
| System.out.println(a1.toString());
|
得到结果
可以使用工具类 Arrays
输出数组
1
| System.out.println(Arrays.toString(a1));
|
输出
copyOf
1 2 3 4 5 6 7
| int[] arr = {1,2,3,4,5}; int[] copied = Arrays.copyOf(arr, 10); System.out.println(Arrays.toString(copied)); copied = Arrays.copyOf(arr, 3); System.out.println(Arrays.toString(copied));
|
输出
1 2
| [1, 2, 3, 4, 5, 0, 0, 0, 0, 0] [1, 2, 3]
|
区别 System.arraycopy()
1 2 3 4 5 6
| int[] arr = {1,2,3,4,5}; int[] copied = new int[10]; System.arraycopy(arr, 0, copied, 1, 5); System.out.println(Arrays.toString(copied));
|
输出
1 2
| [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 1, 2, 3, 4, 5, 0, 0, 0, 0]
|
查看 Arrays.copyOf
源码可知,它是新建了一个数组,然后利用System.arraycopy
将源数组复制到新数组中
1 2 3 4 5
| public static int[] copyOf(int[] original, int newLength) { int[] copy = new int[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
|
asList 使用
1 2
| int[] a1 = { 1, 2, 3 }; List<int[]> list = Arrays.asList(a1);
|
上面的很奇怪, List<int>
和 List<Integer>
会编译不通过,只能改为 List<int[]>
转为 List<int[]>
可以通过这样访问数组 list.get(0)
为什么会这样呢?
List<int>
编译错误,说明没有自动装箱和拆箱,Arrays.asList
常见用法如下
1
| List<Object> objList = Arrays.asList(obj1, obj2, obj3);
|
上面代码将多个输入参数转化为 List
,你也可以传入单个参数
1
| List<Object> objList = Arrays.asList(obj1);
|
而前面也提到了 int[]
是一个对象,继承自Object
, 所以返回了类型参数为 int[]
的 List
推荐 Apache Commons ArrayUtils
下载地址 https://commons.apache.org/proper/commons-lang/download_lang.cgi
它提供了很多工具方法,可以使用下面的代码处理 int
数组
1
| List<Integer> exampleList = Arrays.asList(ArrayUtils.toObject(array));
|
看下 API,public static Integer[] toObject(int[] array)
是将 int[]
转为 Integer[]
也可以这么使用 Arrays.asList
来转化数组
1 2 3
| Integer[] a1 = { 1, 2, 3 }; List<Integer> list = Arrays.asList(a1); System.out.println(list);
|
或者这样
1 2
| List<Integer> list = Arrays.asList(1, 2, 3); System.out.println(list);
|
asList 定长
1 2
| List<Integer> list = Arrays.asList(1, 2, 3); list.add(44);
|
上面的代码会抛出java.lang.UnsupportedOperationException
异常
注意:Arrays.asList
返回的是 Arrays.ArrayList
,不是我们常用的ArrayList
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| private static class ArrayList<E> extends AbstractList<E> { public E get(int index) { return a[index]; } public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } public int indexOf(Object o) { if (o==null) { for (int i=0; i<a.length; i++) if (a[i]==null) return i; } else { for (int i=0; i<a.length; i++) if (o.equals(a[i])) return i; } return -1; } public boolean contains(Object o) { return indexOf(o) != -1; } }
|
Arrays.asList
不支持改变数组长度的操作(add
、 remove
等),看下源码,Arrays.ArrayList
只实现了 get
、 set
、indexOf
、contains
等方法。
Arrays.ArrayList
的父类是AbstractList
,它的 add
和 set
都是throw new UnsupportedOperationException()
1 2 3 4 5 6 7 8 9 10
| public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } }
|
如果需要得到支持add
、remove
的 ArrayList
,可以这样
1
| ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
|
集合转为数组
ArrayList 可以转化为数组,有两个重载的方法
Object[] toArray()
<T> T[] toArray(T[] a)
注意 toArray()
只能得到 Object[]
,无法转型为具体数组类型,比如下面的代码会抛出java.lang.ClassCastException
异常
1 2
| List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); Integer[] arr = (Integer[]) list.toArray();
|
如果需要得到具体类型,需要使用toArray(T[] a)
,传入参数T[] a
1 2 3 4 5 6 7 8 9 10 11 12 13
| ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); Integer[] a1 = new Integer[2]; list.toArray(a1); System.out.println(Arrays.toString(a1)); Integer[] a2 = new Integer[3]; list.toArray(a2); System.out.println(Arrays.toString(a2)); Integer[] a3 = new Integer[4]; list.toArray(a3); System.out.println(Arrays.toString(a3));
|
输出
1 2 3
| [null, null] [1, 2, 3] [1, 2, 3, null]
|
也可以这么使用String[] a = list.toArray(new String[0]);
,new String[0]
只是为了类型信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public <T> T[] toArray(T[] a) { if (a.length < size) return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { 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; }
|
参考文章