java数组与java.util.Arrays工具类
概念
Java中数组属于引用类型。数组使用场合较多,对于数组的操作具有一定重复性,例如:数组拷贝,转换字符串,转换成数组,排序等等。
既然重复的操作与需求多,那么对于数组操作的支持就成了JDK中的一大需求。java.util.Arrays中提供了很多对数组操作的支持。
System.arraycopy: 数组元素拷贝
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
作用是从src数组的srcPos位置往dest数组的destPos位置拷贝length个元素。
当然,数组拷贝位置或元素数量不当时,可能出现ArrayIndexOutOfBoundException异常;类型不匹配时,会出现ArrayStoreException。
int[] a = new int[10];
int[] b = {1,2,3,4,5};
System.out.println("copy all elements of b[5] to a[10]:");
System.arraycopy(b, 0, a, 0, b.length);
System.out.println(Arrays.toString(a));
System.out.println("copy 4 elements of a[10] from index 0 to index 4:");
System.arraycopy(a, 0, a, 4, 4);
System.out.println(Arrays.toString(a));
System.out.println("copy 3 elements of a[10] from index 0 to index 8:");
System.arraycopy(a, 0, a, 8, 3);
System.out.println(Arrays.toString(a));
运行结果:
copy all elements of b[5] to a[10]:
[1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
copy 4 elements of a[10] from index 0 to index 4:
[1, 2, 3, 4, 1, 2, 3, 4, 0, 0]
copy 3 elements of a[10] from index 0 to index 8:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
Arrays.equals: 判断数组内容相等
Arrays中针对不同类型的数组提供了多个重载版本,
包括各种基本类型的比较:
public static boolean equals(int[] a, int[] a2);
public static boolean equals(long[] a, long[] a2);
public static boolean equals(boolean[] a, boolean[] a2);
......
以及对象数组之间的比较:
public static boolean equals(Object[] a, Object[] a2);
示例如下:
int[] a = {1,2,3,4,5};
int[] b = {1,2,3,4,5};
System.out.println("int array compare equal? " + Arrays.equals(a, b));
Integer c[] = {new Integer(1), new Integer(3)};
Integer d[] = {new Integer(1), new Integer(3)};
System.out.println("Integer array compare equal? " + Arrays.equals(c,d));
Integer e[] = {1, 3}; //auto boxing
Integer f[] = {new Integer(1), new Integer(3)};
System.out.println("Integer array of autoBoxing and common Integer array: " + Arrays.equals(e,f));
// int g[] = {1, 3};
// Integer h[] = {new Integer(1), new Integer(3)};
// System.out.println(Arrays.equals(h,g)); //compile error
运行结果:
int array compare equal? true Integer array compare equal? true Integer array of autoBoxing and common Integer array: true
对于最后一个int[]与Integer[]之间的比较,由于jdk中不存在不同类型之间比较的equal方法重载版本,且此处无法自动将int[]转换为封装类型的数组Integer[],因此结果是编译出错。
Arrays.fill: 数组填充内容,Arrays.toString转换字符串
public static void fill(Object[] a, Object val);
此方法将val填充至数组a中的每一个位置。需要注意的是,此处赋值是浅拷贝。
示例如下:
String strings[] = new String[10];
Arrays.fill(strings, "A");
System.out.println(Arrays.toString(strings));
结果如下:
[A, A, A, A, A, A, A, A, A, A]
Arrays.asList:将数组转换为List
public static <T> List<T> asList(T... a);
例如:
String strings[] = new String[10];
Arrays.fill(strings, "A");
List<String> asList = Arrays.asList(strings);
System.out.println(asList);
此方法使用泛型作为参数及返回值,因此当方法参数和返回值List参数类型不一致时,编译器会报错,例如:
int integers[] = {1,2};
// List<Integer> integers1 = Arrays.asList(integers); // compile error
将int[]转换为List<Integer>就会出现编译器报错。
Arrays.sort: 数组排序
sort对于不同类型提供了多个重载版本,例如int[]的排序方法重载版本,排序完成应该是从小至大的顺序:
public static void sort(int[] a);
示例如下:
int[] a = {2,3,1,5,4};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
结果如下:
[1, 2, 3, 4, 5]
下面,针对对象进行排序测试。
对象进行比较的前提是,这种类型'可比较'。那么,它需要实现Comparable<T>接口。
class Person implements Comparable<Person>
{
public Person(int age, String name) {
this.age = age;
this.name = name;
}
int age;
String name;
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Person o) {
return (age-o.age);
}
}
下面构造测试:
Person jack = new Person(21,"jack");
Person rose = new Person(23,"rose");
Person judy = new Person(22,"judy");
Person joo = new Person(24,"joo");
Person persons[] = {jack, rose, judy, joo};
System.out.println(Arrays.toString(persons));
结果如下:
[Person{age=21, name='jack'}, Person{age=23, name='rose'}, Person{age=22, name='judy'}, Person{age=24, name='joo'}]
进行排序:
System.out.println("common sort:");
Arrays.sort(persons);
System.out.println(Arrays.toString(persons));
运行结果:
common sort:
[Person{age=21, name='jack'}, Person{age=22, name='judy'}, Person{age=23, name='rose'}, Person{age=24, name='joo'}]
或者,实现倒序:
System.out.println("reverse sort:");
Arrays.sort(persons, Collections.reverseOrder());
System.out.println(Arrays.toString(persons));
运行结果:
reverse sort:
[Person{age=24, name='joo'}, Person{age=23, name='rose'}, Person{age=22, name='judy'}, Person{age=21, name='jack'}
基于策略模式的自定义Comparator排序
然而,不同人对于相同的对象可能有不同的排序规则。例如,小李想让Person[]按年龄排序,小明想按照Person的名字排序...
基于策略模式,sort的重载版本可指定Comparator<T>作为排序算法:
public static <T> void sort(T[] a, Comparator<? super T> c);
先实现一个对于Person泛型的Comparator类,基于name排序:
class MyComparator implements Comparator<Person>
{
@Override
public int compare(Person o1, Person o2) {
return o1.name.compareTo(o2.name);
}
}
构造测试:
System.out.println("MyComparator:");
Arrays.sort(persons, new MyComparator());
System.out.println(Arrays.toString(persons));
运行结果:
MyComparator:
[Person{age=21, name='jack'}, Person{age=24, name='joo'}, Person{age=22, name='judy'}, Person{age=23, name='rose'}]