java array 方法_Java的Arrays方法分析

2023-05-16

文章结构概览

本文将按一下顺序,逐一介绍。Arrays类介绍

Arrays方法分类排序相关

查找相关

比较相关

打印相关

计算hashCode

拷贝相关

赋值相关

转化为集合List

1. Arrays类介绍This class contains various methods for manipulating arrays (such as

sorting and searching). This class also contains a static factory

that allows arrays to be viewed as lists.

该类包含用于操作数组的各种方法(例如排序和搜索)。该类还包含一个静态工厂,允许将数组视为列表。

根据注释解释,可以知道该类是一个操作数组的工具类,里面封装了常用的数组操作方法。List相关类Arrays相关类图

2. Arrays方法分类

2.1 排序相关

2.1.1 普通排序

int[] numbers = new int[]{2, 8, 1};

// 整体排序System.out.println(Arrays.toString(numbers));

Arrays.sort(numbers);

System.out.println(Arrays.toString(numbers));

// 指定位置排序System.out.println(Arrays.toString(numbers));

Arrays.sort(numbers, 1, 2);

System.out.println(Arrays.toString(numbers));

主要是调用静态方法 sort() ,支持基本类型数组,引用类型数组必须实现 Comparable接口。

其中的排序算法用的是Dual-Pivot Quicksort(双轴快排),升序排序,时间复杂度为O(n log(n))。

/*** Sorts the specified range of the array using the given* workspace array slice if possible for merging** @param a the array to be sorted* @param left the index of the first element, inclusive, to be sorted* @param right the index of the last element, inclusive, to be sorted* @param work a workspace array (slice)* @param workBase origin of usable space in work array* @param workLen usable size of work array*/

static void sort(int[] a, int left, int right, int[] work, int workBase, int workLen) {

// 对于小规模的数组,使用快排 if (right - left < QUICKSORT_THRESHOLD) {

sort(a, left, right, true);

return;

}

/** Index run[i] is the start of i-th run* 索引从i开始* (升序或降序).*/

int[] run = new int[MAX_RUN_COUNT + 1];

int count = 0; run[0] = left;

// 检查数组是否接近有序 for (int k = left; k < right; run[count] = k) {

if (a[k] < a[k + 1]) { // 升序 while (++k <= right && a[k - 1] <= a[k]);

} else if (a[k] > a[k + 1]) { // 降序 while (++k <= right && a[k - 1] >= a[k]);

for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {

int t = a[lo]; a[lo] = a[hi]; a[hi] = t;

}

} else { // 相等 for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {

if (--m == 0) {

sort(a, left, right, true);

return;

}

}

}

/** 如果数组的规模没有超过最大规模,* 应该使用快排,而不是归并排序*/

if (++count == MAX_RUN_COUNT) {

sort(a, left, right, true);

return;

}

}

// 检查特殊情况 // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // 最后一次运行只包含一个元素 run[++count] = right;

} else if (count == 1) { // 数组已经有序 return;

}

// Determine alternation base for merge byte odd = 0;

for (int n = 1; (n <<= 1) < count; odd ^= 1);

// 创建或使用临时数组b int[] b; // temp array; alternates with a int ao, bo; // array offsets from 'left' 相对于left的偏移 int blen = right - left; // space needed for b b所需要的空间 if (work == null || workLen < blen || workBase + blen > work.length) {

work = new int[blen];

workBase = 0;

}

if (odd == 0) {

System.arraycopy(a, left, work, workBase, blen);

b = a;

bo = 0;

a = work;

ao = workBase - left;

} else {

b = work;

ao = 0;

bo = workBase - left;

}

// 合并排序 for (int last; count > 1; count = last) {

for (int k = (last = 0) + 2; k <= count; k += 2) {

int hi = run[k], mi = run[k - 1];

for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {

if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {

b[i + bo] = a[p++ + ao];

} else {

b[i + bo] = a[q++ + ao];

}

}

run[++last] = hi;

}

if ((count & 1) != 0) {

for (int i = right, lo = run[count - 1]; --i >= lo;

b[i + bo] = a[i + ao]

);

run[++last] = right;

}

int[] t = a; a = b; b = t;

int o = ao; ao = bo; bo = o;

}

}

2.1.2 并行排序

int[] numbers = new int[]{2, 8, 1};

// 整体排序System.out.println(Arrays.toString(numbers));

Arrays.parallelSort(numbers);

System.out.println(Arrays.toString(numbers));

// 指定位置排序System.out.println(Arrays.toString(numbers));

Arrays.parallelSort(numbers, 1, 2);

System.out.println(Arrays.toString(numbers));

主要是调用静态方法 parallelSort() ,支持基本数据类型数组,引用类型的数组需要实现Comparable接口,或者调用方法时传入指定的比较器。

这种排序方式,会去判断当前数组的大小是否 小于最小的并行排序长度 MIN_ARRAY_SORT_GRAN,或者并行池的数量为1,如果满足条件,还会调用Dual-Pivot Quicksort(双轴快排)方法来排序,否则才去执行并行排序。

public static void parallelSort(int[] a, int fromIndex, int toIndex) {

rangeCheck(a.length, fromIndex, toIndex);

int n = toIndex - fromIndex, p, g;

if (n <= MIN_ARRAY_SORT_GRAN || (p = ForkJoinPool.getCommonPoolParallelism()) == 1) {

DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);

} else {

new ArraysParallelSortHelpers.FJInt.Sorter

(null, a, new int[n], fromIndex, n, 0,

((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?

MIN_ARRAY_SORT_GRAN : g).invoke();

}

}

2.2 查找相关

int[] numbers = new int[]{2, 8, 1};

// 整体查找int index = Arrays.binarySearch(numbers, 8);

System.out.println("8的对应下标为 " + index);

// 指定位置查找int index2 = Arrays.binarySearch(numbers, 8, 1, 2);

System.out.println("8的对应下标为 " + index2);

主要是调用静态方法 binarySearch() ,支持基本数据类型数组,引用类型的数组需要实现Comparable接口,或者调用方法时传入指定的比较器。

查找算法使用的是二分查找。

private static int binarySearch0(int[] a, int fromIndex, int toIndex, int key) {

int low = fromIndex;

int high = toIndex - 1;

while (low <= high) {

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.}

2.3 比较相关

2.3.1 普通比较

比较数组是否相等:

int[] numbers1 = new int[]{2, 8, 1};

int[] numbers2 = new int[]{2, 6, 1};

// 比较数组是否相等boolean result = Arrays.equals(numbers1, numbers2);

System.out.println("两个数组是否相等 " + result);

支持所有数据类型,其中引用类型会调用equals方法,如果没有重写,则比较的是地址值。

2.3.2 深度比较

针对引用类型,会比较该对象里的所有基本数据类型,如果全部相等,才对比成功。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers1 = new A[]{new A(1), new A(8), new A(0)};

A[] numbers2 = new A[]{new A(2), new A(8), new A(0)};

// 比较数组是否相等boolean result = Arrays.deepEquals(numbers1, numbers2);

System.out.println("两个数组是否相等 " + result);

2.4 打印相关

2.4.1 普通打印

将数组打印出来:

int[] numbers1 = new int[]{2, 8, 1};

// 打印数组System.out.println(Arrays.toString(numbers1));

支持所有数据类型,其中引用类型会调用 toString 方法。

2.4.2 深度打印

针对引用类型,会把该对象里的所有基本数据类型打印出来。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers = new A[]{new A(1), new A(8), new A(0)};

// 打印数组System.out.println(Arrays.deepToString(numbers));

2.5 计算hashCode

2.5.1 普通计算

int[] numbers1 = new int[]{2, 8, 1};

// 打印数组的hash值System.out.println("hashCode " + Arrays.hashCode(numbers1));

支持所有数据类型,其中引用类型会调用 hashCode 方法。

2.5.2 深度计算

针对引用类型,会计算该对象里的所有基本数据类型的hashCode。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers = new A[]{new A(1), new A(8), new A(0)};

// 打印数组的hash值System.out.println("hashCode " + Arrays.deepHashCode(numbers));

2.6 拷贝相关

// 整体拷贝int[] numbers = new int[]{2, 8, 1};

int[] numbers2 = Arrays.copyOf(numbers, 8);

// 打印拷贝的数组System.out.println(Arrays.toString(numbers2));

// 局部拷贝int[] numbers3 = Arrays.copyOfRange(numbers, 1, 8);

System.out.println(Arrays.toString(numbers3));

其中 copyOf 和 copyOfRange 都会调用 System的一个静态方法 arraycopy,如下所示。

public static void arraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {

if (src == null) {

throw new NullPointerException("src == null");

}

if (dst == null) {

throw new NullPointerException("dst == null");

}

if (srcPos < 0 || dstPos < 0 || length < 0 ||

srcPos > src.length - length || dstPos > dst.length - length) {

throw new ArrayIndexOutOfBoundsException(

"src.length=" + src.length + " srcPos=" + srcPos +

" dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length);

}

if (length <= ARRAYCOPY_SHORT_INT_ARRAY_THRESHOLD) {

// Copy int by int for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) {

// Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) {

dst[dstPos + i] = src[srcPos + i];

}

} else {

// Copy forward. for (int i = 0; i < length; ++i) {

dst[dstPos + i] = src[srcPos + i];

}

}

} else {

// Call the native version for longer arrays. arraycopyIntUnchecked(src, srcPos, dst, dstPos, length);

}

}

2.7 赋值相关

可以为一个数组赋上初始值。

// 整体赋值int[] numbers = new int[9];

Arrays.fill(numbers, 8);

System.out.println(Arrays.toString(numbers));

// 局部赋值int[] numbers2 = new int[9];

int value = 9;

Arrays.fill(numbers2, 5, 8, value);

System.out.println(Arrays.toString(numbers2));

2.8 转换为集合List

将一个数组转换成一个List。

class A {

public int a;

public A(int a){

this.a = a;

}

}

A[] numbers = new A[]{new A(1), new A(2)};

List list = Arrays.asList(numbers);

需要注意的是 该List是 Arrays的一个内部类,并不是我们常用的 ArrayList。

并且其只实现了部分方法:Arrays内部的List中实现的方法

调用其他方法 会抛出异常 UnsupportedOperationException。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java array 方法_Java的Arrays方法分析 的相关文章

随机推荐