JDK1.8源码-04-java.util.Arrays

JDK1.8源码-04-java.util.Arrays

java.util.Arrays 类是 JDK 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本都是静态方法,能直接通过类名Arrays调用。

1. asList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Returns a fixed-size list backed by the specified array. (Changes to
* the returned list "write through" to the array.) This method acts
* as bridge between array-based and collection-based APIs, in
* combination with {@link Collection#toArray}. The returned list is
* serializable and implements {@link RandomAccess}.
*
* <p>This method also provides a convenient way to create a fixed-size
* list initialized to contain several elements:
* <pre>
* List&lt;String&gt; stooges = Arrays.asList("Larry", "Moe", "Curly");
* </pre>
*
* @param <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}

作用是返回指定数组支持的固定大小的列表

注意:这个方法返回的ArrayList不是我们常用的集合类java.util.ArrayList。这里的ArrayList是Arrays的一个内部类java.util.Arrays.ArrayList。这个内部类有以下方法和属性:

mark

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;

ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}

@Override
public int size() {
return a.length;
}

@Override
public Object[] toArray() {
return a.clone();
}

@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}

@Override
public E get(int index) {
return a[index];
}

@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}

@Override
public int indexOf(Object o) {
E[] a = this.a;
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;
}

@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}

@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(a, Spliterator.ORDERED);
}

@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
action.accept(e);
}
}

@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
E[] a = this.a;
for (int i = 0; i < a.length; i++) {
a[i] = operator.apply(a[i]);
}
}

@Override
public void sort(Comparator<? super E> c) {
Arrays.sort(a, c);
}
}
  • ==返回的ArrayList数组是一个定长的列表,我们只能对其进行查看或者修改,但是不能进行添加或者删除操作==(通过源码发现该类是没有add()或者remove()方法的,如果对其进行增加或者删除操作,都会调用父类AbstractList对应的方法,而追溯父类的方法最终会抛出UnsupportedOperationException异常。)
1
2
3
4
5
String[] str = {"a","b","c"};
List<String> stringList = Arrays.asList(str);
stringList.set(1,"e"); // 可以进行修改
System.out.println(stringList.toString()); // {a,e,c}
stringList.add("a"); // 添加元素会报错 java.lang.UnsupportedOperationException
  • ==引用类型的数组和基本类型的数组的区别==
1
2
3
4
5
6
7
8
String[] str = {"a","b","c"};
List<String> listStr = Arrays.asList(str);
System.out.println(listStr.size()); // 3


int[] intArr = {1,2,3};
List listInt = Arrays.asList(intArr);
System.out.println(listInt.size()); // 1

上面第一个结果是listStr.size()==3 , 而第二个结果是listInt.size()==1。这个是为什么呢?

我们追到源码去看看,在Arrays,asList中,方法声明是 <T> List<T> asList(T...a)。这就说明这个方法接受的是一个可变长的参数,并且这个可变参数类型是作为泛型的参数。

我们知道基本数据类型是不能作为泛型的参数的,但是数组是引用类型,所以数组是可以泛型化的,于是 int[] 作为了整个参数类型,而不是 int作为参数类型。

所以将上面的方法泛型化补全应该是:

1
2
3
4
5
6
7
8
9
10
11
12
String[] str = {"a","b","c"};
List<String> listStr = Arrays.asList(str);
System.out.println(listStr.size()); // 3


int[] intArr = {1,2,3};
List<int[]> listInt = Arrays.asList(intArr); // 注意这里的List参数是int[] , 而不是int
System.out.println(listInt.size()); // 1

Integer[] in = {1,2,3};
List<Integer> listInteger = Arrays.asList(in); // 这里参数是int的包装类Integer,所以集合长度是3
System.out.println(listInteger.size()); // 3
  • ==返回的列表ArrayList里面的元素都是引用,不是独立出来的对象==
1
2
3
4
5
6
7
8
9
String[] str = {"a","b","c"};
List<String> listStr = Arrays.asList(str);

// 执行更新前的操作
System.out.println(Arrays.toString(str)); // [a,b,c]

// 执行更新后的操作
listStr.set(0,"d"); //将第一个元素改为d
System.out.println(Arrays.toString(str)); // [d,b,c]

这里的Arrays.toString()方法就是打印数组的内容,后面会详细介绍。

我们现在来看修改集合的内容,原数组内容也变化了,所以这里传入的是引用类型。

  • ==已知数组数据,如何快速获取一个可进行增删改查的列表List?==
1
2
3
4
5
// 用ArrayList即可
String[] str2 = {"a","b","c"};
List<String> list = new ArrayList<>(Arrays.asList(str));
list.add("d");
System.out.println(list.size());

这里的ArrayList 集合类后面我们会详细讲解,大家目前只需要知道有这种用法即可。

  • ==Arrays.asList() 方法的使用场景==
  1. Arrays工具类提供了一个方法asList,使用该方法可以将一个变长参数或者数组转换成List。 但是,生成的list长度是固定的;能够进行修改操作(比如:修改某个位置的元素);不能执行影响长度的操作(如add,remove操作),否则会抛出UnsupportedOperationException异常。
  2. 所以Arrays.asList比较适合那些已经有数组数据或者一些元素,而需要快速构建一个list(只用于只读操作,而不进行添加或者删除操作的场景)

2. sort

该方法是用于数组排序,在Arrays类中有该方法的一系列重载方法,能对7种基本数据类型:(byte,char,double,float,int.long,short)等进行排序, 还有Object类型(实现了Comparable接口)以及比较器Comparator。

mark

  • 基本数据类型

这里我们以int[] 为例看看:

1
2
3
4
5
public static void main(String[] args) {
int[] nums = {1,3,8,5,2,4,6,8};
Arrays.sort(nums);
System.out.println(Arrays.toString(nums)); // [1, 2, 3, 4, 5, 6, 8, 8]
}

通过调用sort(int[] a) 方法,将原数组按照升序的顺序排序。下面我们通过源码看看是如何实现排序的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Sorts the specified array into ascending numerical order.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
*/
public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}

通过源码发现在Arrays.sort方法内部调用了DualPivotQuicksort.sort方法,这个方法的源码很长,分别对于数组的长度进行了各种算法的划分,包括快速排序,插入排序,冒泡排序都有使用。

详细的源码解析请参考这篇博客:https://www.cnblogs.com/yuxiaofei93/p/5722714.html ==(有空一定要读一读)==

mark

  • 对象数据类型

该类型的数组进行排序可以实现Comparable接口,重写CompareTo方法进行排序。

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
// 如String实现了Comparable<String>接口
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{

// 重写了compareTo方法
// 具体对于compareTo方法请参考上一篇博客
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;

int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
}
1
2
3
4
// 引用数据类型
String[] str = {"a","c","f","d","b"};
Arrays.sort(str);
System.out.println(Arrays.toString(str)); // [a, b, c, d, f]

String类型实现了Comparable接口,内部的compareTo方法是按照字典码进行排序的。

  • 没有实现Comparable接口的,可以通过Comparator实现排序
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.zhuuu;

import java.util.Arrays;
import java.util.Comparator;

// 没有实现Comparable接口的,可以通过Comparator实现排序
public class TestComparator {
public static void main(String[] args) {
Person[] people = {new Person("张三", 22), new Person("李四", 18), new Person("王五", 15)};

// 通过Comparator实现排序
// 重写compare方法
Arrays.sort(people, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
if (o1 == null || o2 == null){
return 0;
}
return o1.getAge() - o2.getAge();
}
});
System.out.println(Arrays.toString(people));
}
}


// 自定义的Person类,注意这里并没有实现Comparable接口。
class Person{
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public Person() {
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

3. binarySearch

用二分法查找数组中的某个元素。该方法和sort方法一样,适用于各种基本数据类型和对象。

注意:二分法是对有序数组的查找(比如先用Arrays.sort()进行排序,然后再调用此方法进行查找)

1
2
3
4
int[] nums = {1,3,8,5,2,4,6,7};
Arrays.sort(nums);
System.out.println(Arrays.toString(nums)); // [1, 2, 3, 4, 5, 6, 7, 8]
System.out.println(Arrays.binarySearch(nums,2)); // 1

具体底层源码实现:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   /**
* Searches the specified array of ints for the specified value using the
* binary search algorithm. The array must be sorted (as
* by the {@link #sort(int[])} method) prior to making this call. If it
* is not sorted, the results are undefined. If the array contains
* multiple elements with the specified value, there is no guarantee which
* one will be found.
*
* @param a the array to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array;
* otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
* <i>insertion point</i> is defined as the point at which the
* key would be inserted into the array: the index of the first
* element greater than the key, or <tt>a.length</tt> if all
* elements in the array are less than the specified key. Note
* that this guarantees that the return value will be &gt;= 0 if
* and only if the key is found.
*/

public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}

// Like public version, but without range checks.
// 这个二分法应该不用多说了,闭着眼睛都会写才对。
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;

while (low <= high) {
// 除以2
int mid = (low + high) >>> 1;
int 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.
}

4. copyOf

拷贝数组元素。底层采用System.arraycopy()实现,这是一个native方法。

src:源数组

srcPos:源数组要复制的起始位置

dest:目的数组

destPos:目的数组放置的起始位置

length:复制的长度

注意:src 和 dest都必须是同类型或者可以进行转换类型的数组。

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
30
31
32
33
   /**
* Copies the specified array, truncating or padding with zeros (if necessary)
* so the copy has the specified length. For all indices that are
* valid in both the original array and the copy, the two arrays will
* contain identical values. For any indices that are valid in the
* copy but not the original, the copy will contain <tt>0</tt>.
* Such indices will exist if and only if the specified length
* is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros
* to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
* @since 1.6
*/

// @param original 源数组
// @param newLength //返回新数组的长度
public static int[] copyOf(int[] original, int newLength) {
// copy是拷贝后的新数组(长度是newLength)
int[] copy = new int[newLength];
// 调用System.arraycopy方法
// 传入参数长度是(原数组和新数组长度最短的那个)
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}

public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);

测试:

1
2
3
4
5
6
public static void main(String[] args) {
int[] num1 = {1,2,3};
int[] num2 = new int[3];
System.arraycopy(num1,0,num2,0,num1.length);
System.out.println(Arrays.toString(num2));
}

5. equals 和 deepEquals

5.1 equals

equals用来比较两个数组中对应位置的每个元素是否相等

mark

八种基本数据类型以及对象都能进行比较。

我们这里首先看看int类型的数组比较的源码实现。

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
30
31
/**
* Returns <tt>true</tt> if the two specified arrays of ints are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
* of elements in the two arrays are equal. In other words, two arrays
* are equal if they contain the same elements in the same order. Also,
* two array references are considered equal if both are <tt>null</tt>.<p>
*
* @param a one array to be tested for equality
* @param a2 the other array to be tested for equality
* @return <tt>true</tt> if the two arrays are equal
*/
public static boolean equals(int[] a, int[] a2) {
// 数组引用相等,则里面的元素一定相等
if (a==a2)
return true;
// 两个数组其中一个是null,都返回false
if (a==null || a2==null)
return false;
// 两个数组长度不相等,返回false
int length = a.length;
if (a2.length != length)
return false;

// 通过for循环比较数组中每个元素是否相等
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false;

return true;
}

再看对象数组的比较:

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
30
31
32
33
/**
* Returns <tt>true</tt> if the two specified arrays of Objects are
* <i>equal</i> to one another. The two arrays are considered equal if
* both arrays contain the same number of elements, and all corresponding
* pairs of elements in the two arrays are equal. Two objects <tt>e1</tt>
* and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null
* : e1.equals(e2))</tt>. In other words, the two arrays are equal if
* they contain the same elements in the same order. Also, two array
* references are considered equal if both are <tt>null</tt>.<p>
*
* @param a one array to be tested for equality
* @param a2 the other array to be tested for equality
* @return <tt>true</tt> if the two arrays are equal
*/
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++) {
Object o1 = a[i];
Object o2 = a2[i];
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}

return true;
}

基本上也是通过 equals 来判断。

5.2 deepEquals

也是用来比较两个数组的元素是否相等,不过deepEquals能够进行多维数组的比较,而且是任意层次的嵌套数组。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* Returns <tt>true</tt> if the two specified arrays are <i>deeply
* equal</i> to one another. Unlike the {@link #equals(Object[],Object[])}
* method, this method is appropriate for use with nested arrays of
* arbitrary depth.
*
* <p>Two array references are considered deeply equal if both
* are <tt>null</tt>, or if they refer to arrays that contain the same
* number of elements and all corresponding pairs of elements in the two
* arrays are deeply equal.
*
* <p>Two possibly <tt>null</tt> elements <tt>e1</tt> and <tt>e2</tt> are
* deeply equal if any of the following conditions hold:
* <ul>
* <li> <tt>e1</tt> and <tt>e2</tt> are both arrays of object reference
* types, and <tt>Arrays.deepEquals(e1, e2) would return true</tt>
* <li> <tt>e1</tt> and <tt>e2</tt> are arrays of the same primitive
* type, and the appropriate overloading of
* <tt>Arrays.equals(e1, e2)</tt> would return true.
* <li> <tt>e1 == e2</tt>
* <li> <tt>e1.equals(e2)</tt> would return true.
* </ul>
* Note that this definition permits <tt>null</tt> elements at any depth.
*
* <p>If either of the specified arrays contain themselves as elements
* either directly or indirectly through one or more levels of arrays,
* the behavior of this method is undefined.
*
* @param a1 one array to be tested for equality
* @param a2 the other array to be tested for equality
* @return <tt>true</tt> if the two arrays are equal
* @see #equals(Object[],Object[])
* @see Objects#deepEquals(Object, Object)
* @since 1.5
*/
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;
}

static boolean deepEquals0(Object e1, Object e2) {
assert e1 != null;
boolean eq;
if (e1 instanceof Object[] && e2 instanceof Object[])
eq = deepEquals ((Object[]) e1, (Object[]) e2);
else if (e1 instanceof byte[] && e2 instanceof byte[])
eq = equals((byte[]) e1, (byte[]) e2);
else if (e1 instanceof short[] && e2 instanceof short[])
eq = equals((short[]) e1, (short[]) e2);
else if (e1 instanceof int[] && e2 instanceof int[])
eq = equals((int[]) e1, (int[]) e2);
else if (e1 instanceof long[] && e2 instanceof long[])
eq = equals((long[]) e1, (long[]) e2);
else if (e1 instanceof char[] && e2 instanceof char[])
eq = equals((char[]) e1, (char[]) e2);
else if (e1 instanceof float[] && e2 instanceof float[])
eq = equals((float[]) e1, (float[]) e2);
else if (e1 instanceof double[] && e2 instanceof double[])
eq = equals((double[]) e1, (double[]) e2);
else if (e1 instanceof boolean[] && e2 instanceof boolean[])
eq = equals((boolean[]) e1, (boolean[]) e2);
else
eq = e1.equals(e2);
return eq;
}

测试:

1
2
3
4
5
6
public static void main(String[] args) {
String[][] name1= {{"G","A","T"},{"Z","h","u","u","u"}};
String[][] name2= {{"G","A","T"},{"Z","h","u","u","u"}};
System.out.println(Arrays.equals(name1,name2)); //false
System.out.println(Arrays.deepEquals(name1,name2)); //true
}

6. fill

该系列的方法用于给数组复制,并能指定某个范围的赋值。

mark

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
   /**
* Assigns the specified int value to each element of the specified array
* of ints.
*
* @param a the array to be filled
* @param val the value to be stored in all elements of the array
*/

// 给int数组所有元素赋值val
public static void fill(int[] a, int val) {
for (int i = 0, len = a.length; i < len; i++)
a[i] = val;
}


/**
* Assigns the specified int value to each element of the specified
* range of the specified array of ints. The range to be filled
* extends from index <tt>fromIndex</tt>, inclusive, to index
* <tt>toIndex</tt>, exclusive. (If <tt>fromIndex==toIndex</tt>, the
* range to be filled is empty.)
*
* @param a the array to be filled
* @param fromIndex the index of the first element (inclusive) to be
* filled with the specified value
* @param toIndex the index of the last element (exclusive) to be
* filled with the specified value
* @param val the value to be stored in all elements of the array
* @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
* @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
* <tt>toIndex &gt; a.length</tt>
*/

// 给int数组指定从fromIndex开始赋值到toIndex-1 (左闭右开)
public static void fill(int[] a, int fromIndex, int toIndex, int val) {
rangeCheck(a.length, fromIndex, toIndex);
for (int i = fromIndex; i < toIndex; i++)
a[i] = val;
}


// 其中rangeCheck是检查范围是否正确
/**
* Checks that {@code fromIndex} and {@code toIndex} are in
* the range and throws an exception if they aren't.
*/
private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException(
"fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
}
if (fromIndex < 0) {
throw new ArrayIndexOutOfBoundsException(fromIndex);
}
if (toIndex > arrayLength) {
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}

7. toString 和 deepToString

  • toString用来打印一维数组
  • deepToString用来打印多层次嵌套的数组元素

toString源码如下:

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
/**
* Returns a string representation of the contents of the specified array.
* The string representation consists of a list of the array's elements,
* enclosed in square brackets (<tt>"[]"</tt>). Adjacent elements are
* separated by the characters <tt>", "</tt> (a comma followed by a
* space). Elements are converted to strings as by
* <tt>String.valueOf(int)</tt>. Returns <tt>"null"</tt> if <tt>a</tt> is
* <tt>null</tt>.
*
* @param a the array whose string representation to return
* @return a string representation of <tt>a</tt>
* @since 1.5
*/
public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";

StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}

deepToString源码如下:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
* Returns a string representation of the "deep contents" of the specified
* array. If the array contains other arrays as elements, the string
* representation contains their contents and so on. This method is
* designed for converting multidimensional arrays to strings.
*
* <p>The string representation consists of a list of the array's
* elements, enclosed in square brackets (<tt>"[]"</tt>). Adjacent
* elements are separated by the characters <tt>", "</tt> (a comma
* followed by a space). Elements are converted to strings as by
* <tt>String.valueOf(Object)</tt>, unless they are themselves
* arrays.
*
* <p>If an element <tt>e</tt> is an array of a primitive type, it is
* converted to a string as by invoking the appropriate overloading of
* <tt>Arrays.toString(e)</tt>. If an element <tt>e</tt> is an array of a
* reference type, it is converted to a string as by invoking
* this method recursively.
*
* <p>To avoid infinite recursion, if the specified array contains itself
* as an element, or contains an indirect reference to itself through one
* or more levels of arrays, the self-reference is converted to the string
* <tt>"[...]"</tt>. For example, an array containing only a reference
* to itself would be rendered as <tt>"[[...]]"</tt>.
*
* <p>This method returns <tt>"null"</tt> if the specified array
* is <tt>null</tt>.
*
* @param a the array whose string representation to return
* @return a string representation of <tt>a</tt>
* @see #toString(Object[])
* @since 1.5
*/
public static String deepToString(Object[] a) {
if (a == null)
return "null";

int bufLen = 20 * a.length;
if (a.length != 0 && bufLen <= 0)
bufLen = Integer.MAX_VALUE;
StringBuilder buf = new StringBuilder(bufLen);
deepToString(a, buf, new HashSet<Object[]>());
return buf.toString();
}

private static void deepToString(Object[] a, StringBuilder buf,
Set<Object[]> dejaVu) {
if (a == null) {
buf.append("null");
return;
}
int iMax = a.length - 1;
if (iMax == -1) {
buf.append("[]");
return;
}

dejaVu.add(a);
buf.append('[');
for (int i = 0; ; i++) {

Object element = a[i];
if (element == null) {
buf.append("null");
} else {
Class<?> eClass = element.getClass();

if (eClass.isArray()) {
if (eClass == byte[].class)
buf.append(toString((byte[]) element));
else if (eClass == short[].class)
buf.append(toString((short[]) element));
else if (eClass == int[].class)
buf.append(toString((int[]) element));
else if (eClass == long[].class)
buf.append(toString((long[]) element));
else if (eClass == char[].class)
buf.append(toString((char[]) element));
else if (eClass == float[].class)
buf.append(toString((float[]) element));
else if (eClass == double[].class)
buf.append(toString((double[]) element));
else if (eClass == boolean[].class)
buf.append(toString((boolean[]) element));
else { // element is an array of object references
if (dejaVu.contains(element))
buf.append("[...]");
else
deepToString((Object[])element, buf, dejaVu);
}
} else { // element is non-null and not an array
buf.append(element.toString());
}
}
if (i == iMax)
break;
buf.append(", ");
}
buf.append(']');
dejaVu.remove(a);
}

参考文档:https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信