前段时间朋友问了个问题,描述是一个list中想找到目标的下标,当时在忙而且以为他里面存的是对象所以就没多想让他去循环了。今天在复习java的时候发现了一个好玩的东西。
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
System.out.println(list.indexOf("xxx"));
System.out.println(Collections.binarySearch(list,"xxx"));
System.out.println(list.indexOf("ccc"));
System.out.println(Collections.binarySearch(list,"ccc"));
输出结果:
我们看到当找不到的时候indexOf方法返回了个-1而binarySearch方法返回了个-6,如果用了binarySearch方法找目标时if里写了判断不等于-1就会直接裂开。
我们先看看ArrayList中的indexOf方法
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
底层的代码是循环了list用了equals方法比较了传入的object对象找到了就返回下标,如果循环结束还没找到就直接返回-1,这就不管你什么情况只要没有都返回-1。
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
再看看binarySearch方法他这里做了一个判断,选择用哪个方法的原因看看RandomAccess就可以知道,就是判断了一下你的list更适合用迭代器还是更适合用循环来处理。
private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
int low = 0;
int high = list.size()-1;
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = list.get(mid);
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
private static <T>
int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
ListIterator<? extends Comparable<? super T>> i = list.listIterator();
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = get(i, mid);
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
可以看到他并没有像indexOf一样去写死当找不到时返回-1,而且在比较的时候也并没有用equals方法去比较而是用了compareTo方法。compareTo方法会根据内容去进行比较,当长度相同时会比较对应位置的ASCII码差值的负值,如果长度不相同则会返回两个内容的长度差的负值。
我也只是一个菜鸟,内容仅供参考,欢迎大家指出问题。