Java 提供的 Arrays 类里包含了一些 static 修饰的方法 可以直接操作数组.(static 修饰的方法可以直接通过类名调用).Java 8 增强了Arrays类的功能,增加了一些工具方法,可以充分利用多CPU并行的能力来提高设值、排序的性能。
大致分为两类方法,一类是单线方法(用于单线程处理数组),另一类是多线算法(大多以parallel作为前缀,可以充分利用现代CPU多核并行的特点多线程处理数组,特别是对于那些规模非常庞大的数组);
单线程方法:
-
int binarySearch(type[] a,type key)
使用二分法查询key元素值在a数组中出现的索引,如果a数组中不包含key元素值,则返回负数, 调用该方法是要求数组中元素已经按照升序排列,这样才能得到正确结果。 -
int binarySearch(type[] a ,type key,int fromIndex,int toIndex)
重载上一个方法,增加了开始下标和结束下标,规定了查找的范围。调用该方法是要求数组中元素已经按照升序排列,这样才能得到正确结果。
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.
}
获取任意类型的数组,一个对应类型的元素key,还有int类型的开始和结束下标,为了公用一个算法方法,我们先给定两个局部变量,如果没有指定开始和结束下标那么指定从0开始到数组a的长度-1结束。然后循环,循环判定条件是最小范围值小于等于最大范围值。然后中间值和key的比较,确定范围,最后确定key所在位置的index,直接返回。如果没有该值,直接返回负数。
-
type[] copyOf(type[] original,int length)
复制original数组到一个新数组,length为新数组的长度,如果length的值大于original的长度,那么新数组的其他值补0(数值类型),false(布尔类型),null(引用类型)等。如果length的值小于original的长度,那么新数组就是origin数组前length个元素。 -
type[] copyOfRange(type[] original,int fromIndex,int toIndex)
该方法是上面方法的重载,规定了开始复制的下标和结束复制的下标,也就是复制规定位置的数组元素到新数组中。
public static byte[] copyOf(byte[] original, int newLength) {
byte[] copy = new byte[newLength];
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);
Java中这个方法是调用了System类中的arraycopy方法实现的,但是arraycopy有一个修饰符native.方法用native关键字修饰,说明该方法有实现,但不是使用java代码实现的,它的实现是在一个DLL文件中,可能使用C语言等其他语言实现,方便了java和硬件的交互,缺点是增加开销。Native方法也被称为本地方法。
public static byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
byte[] copy = new byte[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
先计算出新数组的长度,使用结束下标-开始下标,如果小于0,说明结束下标小于开始下标,这样不成立,所以手动抛出异常。然后调用System类的arraycopy方法,执行。
-
boolean equals(long[] a1,long[] a2)
判断两个数组的长度和内容是否相同(数组元素必须一一对应并相同)。
public static boolean equals(long[] a, long[] 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 (a[i] != a2[i])
return false;
return true;
}
-
void sort(type[] a)
对数组进行排序 -
void sort(type[] a,int fromIndex,int toIndex)
该方法是上面方法的重载,规定了开始复制的下标和结束复制的下标 String toString(type[] a)
多线方法:都以parallel作为前缀,表示并行计算
- void parallelPrefix(type[] a, int from, int to, typeBinaryOperator op);
i. 表示将数组a的[from, to)进行typeBinaryOperator的二元迭代;
ii. 其中BinaryOperator就是二元操作符的意思;
iii. 该方法的意思其实就是以下代码:
static void parallelPrefix(type[] a, int from, int to, TypeBinaryOperator op) {
for (int i = from; i < to; i++) {
type left = (i == 0)? 1: a[i - 1]; // 对于第一个元素left = 1
type right = a[i];
a[i] = left op right;
}
}
即从头到尾逐个按照left op right的方式更新,那更新后的值继续迭代下一个元素。
iv. 其中typeBinaryOperator表示二元运算法,type目前基本支持Java的基础类型(int、double等),该运算法其实是一个函数式接口,里面只有一个方法:
public interface TypeBinaryOperator {
type applyAsInt(type left, type right);
}
例如上面的如果想使用连乘迭代那就可以直接用Lambda表达式:Arrays.parallelPrefix(arr, 1, 5, (left, right) -> left * right);就行了;
- void parallelPrefix(type[] a, typeBinaryOperator op);
默认区间就是全部[0, length] == [0, length + 1);
如果是数组[1, 2, 3, 4, 5]进行全区间的连乘迭代,得到的结果就是[1, 2, 6, 24, 120];
- void parallelSort(type[] a);
对数组进行排序,与sort相同只是增加了并行能力,可以利用多CPU并行来提高性能。 - void parallelSort(type[] a, int fromIndex, int toIndex);
该方法是上面方法的重载,规定了开始下标和结束下标。 - void parallelSetAll(type[] a, TypeUnaryOperator op);
该方法就是用填充算法为数组a的每个元素赋值; UnaryOperator是一元运算符的意思,之所以是一元是因为该方法默认用元素的索引来生成该元素的值,该接口也是一个函数式接口:
public interface TypeUnaryOperator {
type applyAsInt(type operand); // 利用索引生成一个值,如何生成自己定义
}
该方法的意思就是:
static void parallelSetAll(Type[] a, TypeUnaryOperator op) {
for (int i = 0; i < a.length; i++) {
a[i] = op(i);
}
}
例如:Arrays.parallelSetAll(a, index -> index * 5); // 一个长度为5的int数组其填充结果就是[0, 5, 10, 15, 20]
-
XxxStream stream(xxx[] array)
将数组转为流式,对array进行流式处理,可用一切流式处理的方法Arrays.stream(arrayTest) .map(a->a*2) .filter(a->a>10) .sorted() .distinct() .limit(6) .forEach(a-> System.out.print(a+" ")); System.out.println();