转自https://blog.csdn.net/weixin_41463193/article/details/88653065
万分感谢博主分享!
目录
前言
正文
总结
今天学习到辅助工具类Collections的使用(注意Collection和Collections的区别,前者是一个接口,后者是一个工具类,可以帮助我们对集合进行排序或者查找等操作),Collections中有一个二分查找方法,在使用binarySearch()时,遇到了一些问题,通过查询资料了解到问题的原因,写一篇博客记录一下。
这里直接使用ArrayList新建一个list对象,并向其添加0~9十个元素,然后使用shuffle()打乱一次顺序后,进行二分查找
package cn.hertter.collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestCollections {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i = 0; i < 10; i++) {
list.add(i);
}
System.out.println("原始的顺序:" + list);
Collections.shuffle(list);
System.out.println("打乱后顺序:" + list);
System.out.println("二分查找20:" + Collections.binarySearch(list, 20));
System.out.println("二分查找2:" + Collections.binarySearch(list, 2));
}
}
结果很让我意外,20查不到很正常,但是返回的不是-1而是-11,且连2也查不到。
还是不敢相信,就又重新运行了一遍。
此时查找20的结果还是返回了-11,但是查找2却返回了-2。
莫非,跟顺序有关系?突然想到之前学习的数据结构中,二分查找是有前提条件的!
二分查找必须在有序条件下,才能进行,否则会出错。
我尝试着把集合排一次序再来运行看看,即加上了Collections.sort(list);这一句代码并打印查看。
最终代码变成如下所示:
package cn.hertter.collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestCollections {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i = 0; i < 10; i++) {
list.add(i);
}
System.out.println("原始的顺序:" + list);
Collections.shuffle(list);
System.out.println("打乱后顺序:" + list);
Collections.sort(list);
System.out.println("进行排序后:" + list);
System.out.println("二分查找20:" + Collections.binarySearch(list, 20));
System.out.println("二分查找2:" + Collections.binarySearch(list, 2));
}
}
此时的结果有了变化!2查找到了!
但是又有一个新的问题:为什么查找20时,返回的不是-1而是-11呢?
带着这个疑问,我去查看了binarySearch的源码,如下所示:
其中还没看到具体的查找源码,我又查看了红圈中的源码,如下所示:
大家注意看!其中红圈的部分,返回的是-(low + 1),我们模拟编译器进行一次编译看看!!
模拟编译:
第一次查找时:
low = 0,high = 10 -1 = 9,mid = (9 + 0) / 2 = 4,这里的>>>1,就是除以2的意思
cmp是根据mid与key(这里是我们要查找的20)进行对比
因为4 < 20,所以这里的cmp等于-1。
第一次查找之后,low改变为5,下图可以帮助你们更好的理解。
第二次查找时:
low = 5,high依然为9,mid = (9 + 5) / 2 = 7
因为7 < 20,所以这里的cmp等于-1。
第二次查找之后,low改变为8,过程如下图所示。
第三次查找时:
low = 8,high依然为9,mid = (9 + 8) / 2 = 8
因为8 < 20,所以这里的cmp等于-1。
第三次查找之后,low改变为9,过程如下图所示。
此时low仍然≤high,循环继续
第四次查找时:
low = 9,high依然为9,mid = (9 + 9) / 2 = 9
因为9 < 20,所以这里的cmp等于-1。
第四次查找之后,low改变为10,循环结束!,过程如下图所示。
此时,执行到最后一句,即return -(low + 1);
返回-(10 + 1),即返回-11,也正是我们之前查询的结果!
原来查询不到时不一定返回-1!就像这里面一样,返回的是-11!!!
在学习的过程中,可能会有惯性思维,即若查询不到结果,则返回-1,但是通过今天的探究,发现其实不然。
遇到具体问题需要具体分析,不能形成定性思维!
之前博主以为对二分查找比较熟悉了,但是今天还是遇到了问题,说到底还是基础掌握的不扎实!!!
因此,在今后的学习当中,需要不断巩固一下之前学习的知识,尽量避免在同一个坑中栽了多次!!!