文章目录
- binarySearch
- copyOf()
- deepToString()
- equlas()
- fill()
- sort()
- toString()
binarySearch
public static
int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
public static
int binarySearch(int[] a, int fromIndex, int toIndex,
int key) {
rangeCheck(a.length,
fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
binarySerach()方法是二分查找,如果查找到了就返回下标,如果查找不到就返回一个负值r,-r-1是保持a有序key应该插入的位置。根据形参可看到第一个是在数组a中查找value,第二种则是在范围[ fromIndex , toIndex)中查找,返回的是整个数组的索引,而不是从fromIndex开始的索引。
需要注意的点有两个:
1、如果找不到,返回的是一个负值r,为什么-r-1是本应该插入的位置
2、部分搜索是左闭右开的区间
3、部分搜索是在指定范围内搜索,但是返回的确是整个数组的索引
我们通过源代码来解析一下
这两种方法都调用了binarySearch0(),我们来看看源代码
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.
}
这是一个私有方法,只供jdk内部调用,Arrays的源码里面还有很多binarySearch()的重载方法,区别在于类型的不同,这里举的例子是int型数组。
定义了low和high两个变量,通过high的定义我们就知道了 第二点部分搜索是左闭右开
int high = toIndex - 1;
在进行搜索的时候,直接将最大边界减一,所以肯定不会包括右边界了
当找到key值的时候,我们可以看到返回的是mid
下来我们看看while循环,这个算法的思路就是先找到中间元素(必须提前排序),然后和key进行比较,如果key值大了,就抛弃中间往前所有的元素,让low为抛弃后的第一个元素,如果小了相反。这样一直缩小区间直到退出循环。退出循环也就是low=high,所以这个时候low也就是high就代表了数组中该值的索引位置。
当找到元素的时候,直接返回mid索引
return mid; // key found
再往上追溯可以看到比较的是a[mid]
int midVal = a[mid];
所以这些都是原来数组的索引,返回的也是原来的,只不过搜索范围变了
如果找不到,返回-(low+1)
return -(low + 1); // key not found.
上面我们已经说过,退出while循环的条件是low等于high,low也就是这个数字如果数组中存在,本来应该的位置,但是返回却是-(low+1),如果返回的是r,那么-r-1就是该值如果存在,它的位置。
copyOf()
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;
}
这个方法用于数组的拷贝,先来介绍一下用法,original数组是被拷贝数组,newLength是需要拷贝的长度,从数组的0号下标开始计算,如果大于数组的长度,那么只拷贝整个数组长度
我们可以看到底层调用了System.arraycopy()方法,我们去看看这个方法。
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
它的底层是调用了c或者c++(native修饰),所以看不到具体实现
如果想要详细了解java的拷贝,可以点开这里java数组的四种拷贝 copyOfRange()方法不过是限制了拷贝的范围,底层都是调用了System.arraycopy()只不过传参不一样了,我推荐还是使用System.arraycopy()这个方法的优点是很灵活。
deepToString()
这个方法用于打印二维数组
int[][] array = {
{1,2,3},
{3,4,5},
{1,22,7},
};
System.out.println(Arrays.deepToString(array));
equlas()
public static boolean equals(int[] a, int[] 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;
}
我们知道数组是引用类型,“==”在比较引用类型的时候比较的是地址,所以我们在比较数组的值的时候就要用这个方法。
我们可以看到它首先判断的是有没有可能是两个引用指向同一个地址,如果是则直接返回true,下来判断是否为空,如果其中一个为空就不用继续向下了,然后比较的是长度,最后才去遍历每一个比较值。
fill()
public static void fill(int[] a, int val) {
for (int i = 0, len = a.length; i < len; i++)
a[i] = val;
}
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;
}
这个方法是给数组填充值,代码非常简单,通过一个for循环给数组元素赋值,第一个方法是给整个范围赋值val,第二个则是给范围内赋值,范围是左闭右开。
sort()
public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
sort()方法的功能是排序,底层调用优化的快速排序,后续补充。
toString()
int[] array = {1,2,3,4,5,6};
System.out.println(Arrays.toString(array));
这个方法主要用于输出一维数组。