Arrays类
方法
toString / deepToString
-
将一维/多维数组转换成字符串
-
使用toString方法遍历输出数组,可以替代自己编写的for循环
public static String toString(int[] a) { if (a == null) return "null"; int iMax = a.length - 1; if (iMax == -1) return "[]"; //StringBuilder可变字符串对象,但没有实现线程安全功能,所以性能比StringBuffer略高。 StringBuilder b = new StringBuilder(); b.append('['); for (int i = 0; ; i++) { b.append(a[i]); if (i == iMax) return b.append(']').toString(); b.append(", "); } }
-
Demo
public static void main(String[] args){ int[] arr = {8,1,2,3,4,5,6,7}; System.out.println(arr); System.out.println(Arrays.toString(arr)); } Output: [I@10f87f48 // 哈希值?内存地址 [8, 1, 2, 3, 4, 5, 6, 7]
binarySearch
- 二分查找,返回查找值的下标
// Like public version, but without range checks.
private static int binarySearch0(long[] a, int fromIndex, int toIndex,
long key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
long midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
- Demo
public static void main(String[] args){
int[] arr = {8,1,2,3,4,5,6,7};
System.out.println(Arrays.binarySearch(arr,2));
}
Output:
2
sort
方法信息:public static String toString(Array[] array, int fromIndex, int toIndex)
参数1数组,
(参数2,3可以没有)参数2,3为数组索引位置,用来对指定范围的数据进行排序
排序范围: [fromIndex, toIndex)
将数组进行升序排序
public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
DualPivotQuicksort.sort(a, 0, fromIndex, toIndex);
}
- 默认升序Demo
public static void main(String[] args){
int[] arr = {8,1,2,3,6,4,5,7};
System.out.println(arr);
System.out.println(Arrays.toString(arr));
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
Output:
[I@10f87f48
[8, 1, 2, 3, 6, 4, 5, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
public static void main(String[] args){
int[] arr = {8,1,2,3,6,4,5,7};
System.out.println(arr);
System.out.println(Arrays.toString(arr));
Arrays.sort(arr,0,5);
System.out.println(Arrays.toString(arr));
}
Output:
[I@10f87f48
[8, 1, 2, 3, 6, 4, 5, 7]
[1, 2, 3, 6, 8, 4, 5, 7]
-
降序Demo
- 方法一:实现Comparator接口的复写compare()方法:
public static void main(String[] args) { Integer[] array = {8,1,2,3,6,4,5,7}; System.out.println(array); System.out.println(Arrays.toString(array)); Comparator<Integer> cmp = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // return o1-02; 升序 return o2-o1; // 降序 } }; Arrays.sort(array, cmp); System.out.println(Arrays.toString(array)); }
- 方法二:Arrays.sort(a,Collections.reverseOrder())
- 不支持基本类型(int,double,char等),如果是int型需要改成Integer,float要改成Float。
public static void main(String[] args){
Integer[] array = {8,1,2,3,6,4,5,7};
System.out.println(array);
System.out.println(Arrays.toString(array));
// 必须是包装类
//Arrays.sort(arr, Collections.reverseOrder());
Arrays.sort(array, Collections.reverseOrder());
System.out.println(Arrays.toString(array));
}
copyOf
- 用于复制指定的数组内容以达到扩容的目的,该方法对不同的基本数据类型都有对应的重载方法
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;
}
- Demo
public static void main(String[] args){
int[] arr = {8,1,2,3,6,4,5,7};
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
arr = Arrays.copyOf(arr,10);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
}
Output:
8
[8, 1, 2, 3, 6, 4, 5, 7]
10
[8, 1, 2, 3, 6, 4, 5, 7, 0, 0]
copyOfRange
- 复制指定范围的数组
public static int[] copyOfRange(int[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
int[] copy = new int[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
-
Demo
public static void main(String[] args){ int[] arr = {8,1,2,3,6,4,5,7}; System.out.println(arr.length); System.out.println(Arrays.toString(arr)); arr = Arrays.copyOfRange(arr,0,5); System.out.println(arr.length); System.out.println(Arrays.toString(arr)); } Output: 8 [8, 1, 2, 3, 6, 4, 5, 7] 5 [8, 1, 2, 3, 6]
equals / deepEquals
equals
- 用于比较一维数组,包括了八大基础数据和引用数据。java内置的八大基础数据类型不属于引用数据,故而没有equals方法,如果要比较基础数据类型的值是否相等,需要使用Arrays.equals方法
public static boolean equals(Object[] a, Object[] a2) {
if (a==a2)
return true;
if (a==null || a2==null)
return false;
int length = a.length;
if (a2.length != length)
return false;
for (int i=0; i<length; i++) {
if (!Objects.equals(a[i], a2[i]))
return false;
}
return true;
}
deepEquals(Object[] o1,Object[] o2)
- 比较引用数据的多维数组的各元素是否相等
public static boolean deepEquals(Object[] a1, Object[] a2) {
if (a1 == a2)
return true;
if (a1 == null || a2==null)
return false;
int length = a1.length;
if (a2.length != length)
return false;
for (int i = 0; i < length; i++) {
Object e1 = a1[i];
Object e2 = a2[i];
if (e1 == e2)
continue;
if (e1 == null)
return false;
// Figure out whether the two elements are equal
boolean eq = deepEquals0(e1, e2);
if (!eq)
return false;
}
return true;
}
- Demo
public static void main(String[] args) {
int[] array1 = {1,2,3};
int[] array2 = {1,2,3};
int[] array3 = {1,2,4};
System.out.println(Arrays.equals(array1,array2)); // 数组的比较,返回true
System.out.println(Arrays.equals(array1,array3)); // 数组的比较,返回false
}
public static void main(String[] args) {
Integer[][] array1 = {{1,2,3}};
Integer[][] array2 = {{1,2,3}};
Integer[][] array3 = {{1,2,4}};
System.out.println(Arrays.equals(array1,array2)); // 多维数组的比较,返回false
System.out.println(Arrays.equals(array1,array3)); // 多维数组的比较,返回false
System.out.println(Arrays.deepEquals(array1,array2)); // 多维数组深比较,判断是值相同,返回true
}
-
总结:
在一维数组中,使用 Arrays.equals 或者 Arrays.deepEquals 都可以判断其中的值是否相同。
但在二维及以上,只能使用 Arrays.deepEquals来判断其中的值是否相同。
深拷贝 浅拷贝
概念
-
浅拷贝:
-
浅拷贝是指在拷贝对象时,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用进行拷贝,没有对引用指向的对象进行拷贝。
-
Array是引用类型,直接用“=”号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,并没有实现数组的数据的拷贝。
-
-
深拷贝:开辟新的储存空间,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
数组拷贝类型分类
(以下几种都是浅拷贝)
- 循环赋值
- System.arraycopy()
- Arrays.copyOf() / Arrays.copyOfRange()
- Object.clone()
效率:
System.arraycopy > clone > Arrays.copyOf > for循环
for
for循环是一种很灵巧的数组拷贝方式,经常可以自己封装成方法去使用。
System.arraycopy()
通过System类调用的静态方法,我们先看看源码
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
- src代表被拷贝的对象,srcPos代表起始位置,dest代表目标对象,destpost代表目标对象的起始位置,length代表拷贝的长度。
- native修饰,所以底层也是用c或者c++实现的;
- 由于没有返回值,clone()还需要对返回值进行类型转换,所以它的速度是要比clone()要快的。
Arrays.copyof()
这个方法是属于Arrays类的,在源码中提供了很多方法的重载:
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;
}
-
original是待拷贝对象,newLength表示拷贝的长度
-
在方法内部调用了System.arraycopy(),所以速度比System.arraycopy()慢。
Object.clone()
protected native Object clone() throws CloneNotSupportedException;
- 修饰符native,说明是由c或者c++实现的,它的优点是速度快,它返回了object对象,所以使用的时候需要用对象接收返回值。