java中的Arrays这个工具类你真的会用吗

Java源码系列三-工具类Arrays

​ 今天分享java的源码的第三弹,Arrays这个工具类的源码。因为近期在复习数据结构,了解到Arrays里面的排序算法和二分查找等的实现,收益匪浅,决定研读一下Arrays这个类的源码。不足之处,欢迎在评论区交流和指正。

1.认识Arrays这个类:

​ 首先它在java的utils包下,属于Java Collections Framework中的一员。它的初衷就是一个工具类,封装了操纵数组的各种方法,比如排序,二分查找,数组的拷贝等等。满足了我们日常对数组操做的基本需求,了解它的底层实现,不仅能帮助我们更好的使用它,而且还能培养我们更好的代码的思维。

2.构造方法

​ 因为是一个工具类,所以它的构造方法定义为私有的,且所有的实现方法都是静态方法。也就是说这个类不能被实例化,通俗的讲,就是不能new。只能通过类名来直接调用方法(反射除外)。这样做的目的是强化该类不可实列化的能力,突出该类作为工具类的根本职能。源码如下:

// Suppresses default constructor, ensuring non-instantiability. private Arrays() {} 3.常用方法的解析 3.1快速插入集合元素的方法asList(T... a):

基本使用:

/** * 数组转化为集合 */ @Test public void toArrayTest(){ List<Integer> list = Arrays.asList(2,4,5,6,6); for (Integer integer : list) { System.out.print(integer+" "); } }

输出结果:

2 4 5 6 6

看一下源码:

@SafeVarargs @SuppressWarnings("varargs") public static <T> List<T> asList(T... a) { return new ArrayList<>(a); } // ArrayList的构造方法和属性 private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); }

​ 这个方法的实现比较简单,就是调用ArrayList的构造方法,并且参数是一个数组,也就是将我们要构造的数传入到ArrayList的构造方法中去,进行实例化。

3.2.二分查找的方法

Arrays类中的二分查找八种基本类型都有涉及,但都是方法的重载。其实现原理都是一样,这里以int类型为例,进行说明。

基本使用:

@Test public void binarySearchTest(){ int[] arrays = {1,4,6,7,9,3}; // 查找元素为7的下标值 int result = Arrays.binarySearch(arrays,7); System.out.println(result); }

结果:

3

这个方法主要涉及的一下三个方法:

// 我们常用的方法 public static int binarySearch(int[] a, int key) { return binarySearch0(a, 0, a.length, key); } /* 参数说明如下: a 待查找的数组 fromIndex 查找的开始位置 toIndex 查找的结束位置 key 查找的目标值 */ public static int binarySearch(int[] a, int fromIndex, int toIndex, int key) { // 进行异常检查 rangeCheck(a.length, fromIndex, toIndex); return binarySearch0(a, fromIndex, toIndex, 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) { // 找出查找范围的中间值 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. }

当然实现的核心方法还是上述私有方法binarySearch0()这个方法,实现的逻辑也不复杂。

第一步就是声明两个变量存储查找区域的开始和结束。

第二步 循环,比较,不断的缩小比较的范围,直到找到数组中的值和目标值相同,返回下标,如果没有找到就返回一个负数也就是下面的这l两行代码:

return mid; // key found return -(low + 1); // key not found.

我认为:这个二分法实现的亮点就在于求中间值的移位运算:

int mid = (low + high) >>> 1;

有人就纳闷了,为什么还要使用移位运算,除法不行吗?主要还是为了性能考量。因为移位运算占两个机器周期,而乘除法占四个运算周期,所以移位运算的速度肯定比乘除法的运算速度快很多,计算量小了可能区别不大,但是计算量很大,就区别很明显了。

3.3 数组的拷贝 @Test public void testCopyArrange(){ // 原数组 int [] srcArray = {11,2,244,5,6,54}; // 拷贝原数组长度为3的部分 int[] descArray = Arrays.copyOf(srcArray,3); System.out.println(Arrays.toString(descArray)); }

输出结果:

[11, 2, 244]

源码分析:

/* 参数说明: original 原数组 newLength 拷贝的数组长度 */ 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; } public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zggwxs.html