Arrays工具类
数组转集合asList
- 将数组转换为集合,接收一个可变参数
<T> List<T> asList(T... a);
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3);
list1.forEach(System.out::println); // 1 2 3
Integer[] data = {1, 2, 3};
List<Integer> list2 = Arrays.asList(data);
list2.forEach(System.out::println); // 1 2 3
}
注意:该方法返回的是 Arrays 内部静态类 ArrayList,而不是我们平常使用 java.util.List
包下的 ArrayList。由于该静态类的底层采用大小固定的数组,所以任何对该 list 的添加、删除操作都会抛出异常。
填充数组fill
- 用指定元素填充整个数组
//有多个不同数据类型的重载方法,此处列出一个
void fill(Object[] a, Object val);
public static void main(String[] args) {
Integer[] data = {1, 2, 3, 4};
Arrays.fill(data, 5);
System.out.println(Arrays.toString(data)); // [5, 5, 5, 5]
}
- 用指定元素填充数组,从 fromIndex 位置开始(包括)到 toIndex 位置结束(不包括)
//有多个不同数据类型的重载方法,此处列出一个
public static void fill(Object[] a, int fromIndex, int toIndex, Object val);
public static void main(String[] args) {
Integer[] data = {1, 2, 3, 4};
Arrays.fill(data, 0, 2, 5);
System.out.println(Arrays.toString(data)); // [5, 5, 3, 4]
}
排序sort/parallelSort
- 对数组元素从小到大进行排序。对于元素类型为基本类型,采用一种快速排序算法,该排序算法是不稳定的;对于元素类型为引用类型,采用归并排序,该排序算法是稳定的。
//有多个不同数据类型的重载方法,此处列出一个
void sort(Object[] a);
public static void main(String[] args) {
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
Arrays.sort(data);
System.out.println(Arrays.toString(data)); // [1, 2, 3, 4]
}
- 对 fromIndex 位置开始(包括)开始到 toIndex 位置结束(不包括)的数组元素进行排序。
//有多个不同数据类型的重载方法,此处列出一个
void sort(Object[] a, int fromIndex, int toIndex);
public static void main(String[] args) {
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
Arrays.sort(data, 0, 3);
System.out.println(Arrays.toString(data)); // [1, 3, 4, 2]
}
- 使用自定义比较器,对数组元素进行排序
void sort(T[] a, Comparator<? super T> c);
public static void main(String[] args) {
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 实现字典序降序排列
// 比较器返回正数,o1和o2换位置;返回0,o1和o2位置不变;返回负数,o1和o2位置不变
Arrays.sort(data, (o1, o2) -> o2.compareTo(o1));
System.out.println(Arrays.toString(data)); // [4, 3, 2, 1]
}
- 使用自定义比较器,对 fromIndex 位置开始(包括)开始到 toIndex 位置结束(不包括)的数组元素进行排序
void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
public static void main(String[] args) {
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 实现字典序降序排列
// 比较器返回正数,o1和o2换位置;返回0,o1和o2位置不变;返回负数,o1和o2位置不变
Arrays.sort(data, 0, 3, (o1, o2) -> o2.compareTo(o1));
System.out.println(Arrays.toString(data)); // [4, 3, 1, 2]
}
- 上面的情况都是单核(串行)进行排序,下列方式是多核(并行)进行排序,当数据规模较大时,会有更好的性能,其余重载方法和上面类似。
public static <T extends Comparable<? super T>> void parallelSort(T[] a);
public static void main(String[] args) {
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
Arrays.parallelSort(data);
System.out.println(Arrays.toString(data)); // [1, 2, 3, 4]
}
查找binarySearch
- 使用二分法查找正序的数组 a 中的指定元素 key,如果在数组中找到该元素,返回该元素的索引值;如果未查找到该元素,返回
-(最后一次查找的索引值 + 1)
,因此返回负数即为查找未成功。
//有多个不同数据类型的重载方法,此处列出一个
int binarySearch(Object[] a, Object key);
//a 数组必须已经根据 Comparator 排好序
int binarySearch(T[] a, T key, Comparator<? super T> c);
public static void main(String[] args) {
Integer[] data = {1, 5, 3, 7};
//查找前的数组必须是正序的
Arrays.sort(data);
System.out.println(Arrays.toString(data)); //[1, 3, 5, 7]
System.out.println(Arrays.binarySearch(data, 3)); //1
//查找小于数组最小元素的数
//程序会把数组看作 {0, 1, 3, 5, 7},此时0的索引值为0,则搜索0时返回 -(0 + 1) = -1
System.out.println(Arrays.binarySearch(data, 0)); //-1
//查找大于数组最大元素的数
//程序会把数组看作 {1, 3, 5, 7, 10},此时10的索引值为4,则搜索10时返回 -(5 + 1) = -5
System.out.println(Arrays.binarySearch(data, 10)); //-5
//查找不是数组元素,但在数组范围内的数
//程序会把数组看作 {1, 3, 5, 6, 7},此时6的索引值为3,则搜索10时返回 -(3 + 1) = -4
System.out.println(Arrays.binarySearch(data, 6)); //-4
}
- 使用二分法查询数组从 fromIndex 位置开始(包括)开始到 toIndex 位置结束(不包括)范围内的指定元素的索引值。
//有多个不同数据类型的重载方法,此处列出一个
int binarySearch(Object[] a, int fromIndex, int toIndex, Object key);
//a 数组必须已经根据 Comparator 排好序
int binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c);
public static void main(String[] args) {
Integer[] data = {1, 5, 3, 7};
//查找前的数组必须是正序的
Arrays.sort(data);
System.out.println(Arrays.toString(data)); //[1, 3, 5, 7]
System.out.println(Arrays.binarySearch(data, 0, 2, 3)); //1
//程序会把数组看作 {0, 1, 3},此时0的索引值为0,则搜索0时返回 -(0 + 1) = -1
System.out.println(Arrays.binarySearch(data, 0, 2, 0)); //-1
//程序会把数组看作 {1, 3, 10},此时10的索引值为2,则搜索10时返回 -(2 + 1) = -3
System.out.println(Arrays.binarySearch(data, 0, 2, 10)); //-3
}
拷贝数组copyOf/copyOfRange/arraycopy
- 拷贝数组,其内部调用了
System.arraycopy()
方法,从下标 0 开始,如果超过原数组长度,则会用 null 进行填充。
//有多个不同数据类型的重载方法,此处列出一个
T[] copyOf(T[] original, int newLength);
public static void main(String[] args) {
Integer[] data1 = {5, 4, 3, 2};
Integer[] data2 = Arrays.copyOf(data1, 2);
System.out.println(Arrays.toString(data2)); // [5, 4]
Integer[] data3 = Arrays.copyOf(data1, 5);
System.out.println(Arrays.toString(data3)); // [5, 4, 3, 2, null]
}
- 拷贝从 from 位置开始(包括)开始到 to 位置结束(不包括)范围内的数组元素,如果超过原数组长度,则会用 null 进行填充。
//有多个不同数据类型的重载方法,此处列出一个
T[] copyOfRange(T[] original, int from, int to);
public static void main(String[] args) {
Integer[] data1 = {5, 4, 3, 2};
Integer[] data2 = Arrays.copyOfRange(data1, 0, 2);
System.out.println(Arrays.toString(data2)); // [5, 4]
Integer[] data3 = Arrays.copyOfRange(data1, 0, 5);
System.out.println(Arrays.toString(data3)); // [5, 4, 3, 2, null]
}
- arraycopy 不是 Arrays 类的方法,而是 System 类。该方法可以将 src 数组里从 srcPos 开始的 length 个的元素拷贝给 dest 数组的元素,destPos 是 dest 数组的赋值起始位置。
void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
public static void main(String[] args) {
Integer[] data1 = {5, 4, 3, 2, 1};
Integer[] data2 = new Integer[5];
System.arraycopy(data1, 1, data2, 0, 3);
System.out.println(Arrays.toString(data1)); //[5, 4, 3, 2, 1]
System.out.println(Arrays.toString(data2)); //[4, 3, 2, null, null]
}
判断相等equals/deepEquals
- 判断两个数组是否相等,如果 a 和 a2 指向同一个数组对象,返回 true; 如果 a 和 a2 指向不同的数组对象,对于基本类型元素直接判断它们是否相等,对于引用类型元素调用它们的 equals 方法进行比较,都为 true,最终才返回true。
//有多个不同数据类型的重载方法,此处列出一个
boolean equals(Object[] a, Object[] a2);
public static void main(String[] args) {
Integer[] data1 = {1, 2, 3};
Integer[] data2 = {1, 2, 3};
System.out.println(Arrays.equals(data1, data2)); // true
//数组对象没有重写equals方法,默认判断的是data1 == data2,是否为同个数组对象引用
System.out.println(data1.equals(data2)); //false
}
- 判断两个多维数组是否相等,判断方式和 equals 差不多。
boolean deepEquals(Object[] a1, Object[] a2);
public static void main(String[] args) {
Integer[][] data1 = {{1,2,3}, {1,2,3}};
Integer[][] data2 = {{1,2,3}, {1,2,3}};
System.out.println(Arrays.deepEquals(data1, data2)); // true
}
返回哈希值hashCode/deepHashCode
- 该方法计算并返回数组的哈希值
//有多个不同数据类型的重载方法,此处列出一个
int hashCode(Object a[]);
public static void main(String[] args) {
Integer[] data1 = {1, 2, 3};
Integer[] data2 = {1, 2, 3};
System.out.println(Arrays.hashCode(data1)); //30817
//数组对象没有重写hashCode方法,默认返回的是地址的哈希值
System.out.println(data1.hashCode()); //460141958
System.out.println(Arrays.hashCode(data2)); //30817
System.out.println(data2.hashCode()); //1163157884
}
- 该方法计算并返回多维数组的哈希值
int deepHashCode(Object a[]);
public static void main(String[] args) {
Integer[][] data1 = {{1, 2, 3}, {1, 2, 3}};
Integer[][] data2 = {{1, 2, 3}, {1, 2, 3}};
System.out.println(data1.hashCode()); //460141958
System.out.println(Arrays.deepHashCode(data1)); //987105
System.out.println(data2.hashCode()); //1163157884
System.out.println(Arrays.deepHashCode(data2)); //987105
}
字符串格式toString/deepToString
- 该方法将一个数组转换成一个字符串,多个数组元素使用英文逗号和空格隔开。要求该数组的引用类型元素重写了 toString() 方法,因为该方法拼接的是元素的 toString() 返回值。
//有多个不同数据类型的重载方法,此处列出一个
String toString(Object[] a);
public static void main(String[] args) {
Integer[] data = {1, 2, 3};
System.out.println(Arrays.toString(data)); // [1, 2, 3]
//数组对象没有重写toString方法,默认返回的是地址的哈希值
System.out.println(data.toString()); //[Ljava.lang.Integer;@1b6d3586
}
- 返回多维数组的字符串格式。
String deepToString(Object[] a);
public static void main(String[] args) {
Integer[][] data = {{1, 2, 3}, {1, 2, 3}};
System.out.println(Arrays.deepToString(data)); // [[1, 2, 3], [1, 2, 3]]
}
元素生成器setAll/parallelSetAll
- 让数组中的所有元素,串行使用方法提供的生成器函数来计算每个元素。
//有多个不同数据类型的重载方法,此处列出一个
void setAll(T[] array, IntFunction<? extends T> generator);
public static void main(String[] args) {
Integer[] data = {1, 2, 3, 4};
// i为数组索引值
Arrays.setAll(data, i -> data[i] * 2);
System.out.println(Arrays.toString(data)); // [2, 4, 6, 8]
}
- 让数组中的所有元素,并行使用方法提供的生成器函数来计算每个元素,当数据规模较大时,会有更好的性能。
//有多个不同数据类型的重载方法,此处列出一个
void parallelSetAll(T[] array, IntFunction<? extends T> generator);
public static void main(String[] args) {
Integer[] data = {1, 2, 3, 4};
// i为索引值
Arrays.parallelSetAll(data, i -> data[i] * 2);
System.out.println(Arrays.toString(data)); // [2, 4, 6, 8]
}
数组转Stream对象stream
- 该方法将数组转换为 Stream, Stream 是
JDK 1.8
新增的流式编程的 API。
//有多个不同数据类型的重载方法,此处列出一个
Stream<T> stream(T[] array);
public static void main(String[] args) {
Integer[] data = {1, 2, 3, 4};
List<Integer> list = Arrays.stream(data).collect(toList());
System.out.println(list); //[1, 2, 3, 4]
}
- 该方法将从 startInclusive 位置开始(包括)开始到 endExclusive 位置结束(不包括)范围内的数组元素转换为 Steam。
//有多个不同数据类型的重载方法,此处列出一个
Stream<T> stream(T[] array, int startInclusive, int endExclusive);
public static void main(String[] args) {
Integer[] data = {1, 2, 3, 4};
List<Integer> list = Arrays.stream(data, 0, 3).collect(toList());
System.out.println(list); // [1, 2, 3]
}
参考: https://blog.csdn.net/Goodbye_Youth/article/details/81003817