功能抄自JDK的Collections类,但源码不支持倒叙查找,做了一点点改动,使其支持。
见代码,注释很详细,就不啰嗦了。
private static final int BINARYSEARCH_THRESHOLD = 5000;
/**
*
* 功能描述:从指定list中,二分查找指定元素指定字段值,如在list<PrintBox> 中,查找字段FModel值为x的对象
* ,list内的泛型元素须实现了Comparable接口并重写了compareTo方法
* list须提前排序,正序倒序均可
* 当list对象未实现RandomAccess接口或list.size()> 5000时,使用基于迭代器的二分法查找,反之,则基于索引的二分法查找。
* 对于实现了RandomAccess接口的list,索引循环会比迭代器更快,如ArrayList
* @Author 李
* @MethodName getBinarySearch
* @Date 17:47 2021/6/4
* @param <T> list中的对象的类
* @param list 被查找的list,建议用ArrayList,比较快
* @param key 用于查找的对象,该对象中重写比较器时所用的用于比较的字段需有值
* @return int 返回符合指定元素指定字段值的元素下标
* @exception
**/
public static <T> int getBinarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size() < BINARYSEARCH_THRESHOLD) {
return indexBinarySearch(list, key);
} else {
return iteratorBinarySearch(list, key);
}
}
/**
* 功能描述:基于迭代器的二分查找,list须提前排序,正序倒序均可
* @param list
* @param key 用于查找的对象,该对象中重写比较器时所用的用于比较的字段需有值
* @return int
* @throws
* @Author 李
* @MethodName getBinarySearch
* @Date 11:37 2021/6/4
**/
private static <T> int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key) {
int start = 0;
int end = list.size() - 1;
boolean flag = isReverse(list);
ListIterator<? extends Comparable<? super T>> i = list.listIterator();
while (start <= end) {
int middle = (end + start) >>> 1;
Comparable<? super T> midVal = getIterator(i, middle);
int cmp = midVal.compareTo(key);
if (flag){
cmp *= (-1);
}
if (cmp < 0) {
start = middle + 1;
} else if (cmp > 0) {
end = middle - 1;
} else {
return middle;
}
}
return -(start + 1);
}
/**
*
* 功能描述:基于下标索引的二分查找,list须提前排序,正序倒序均可
* @Author 李
* @MethodName indexBinarySearch
* @Date 17:45 2021/6/4
* @param list
* @param key 用于查找的对象,该对象中重写比较器时所用的用于比较的字段需有值
* @return int
* @exception
**/
private static <T> int indexBinarySearch(List<? extends Comparable<? super T>> list, T key) {
int start = 0;
int end = list.size() - 1;
//第一个比最后一个大时,说明是倒序的。
boolean flag = isReverse(list);
while (start <= end){
int middle = (end + start) >>> 1;
Comparable<? super T> midVal = list.get(middle);
int cmp = midVal.compareTo(key);
if (flag){//倒序时,须反转正负
cmp *= (-1);
}
if (cmp < 0) {
start = middle + 1;
} else if (cmp > 0) {
end = middle - 1;
} else {
return middle;
}
}
return -(start + 1);
}
/**
*
* 功能描述:判断一个list是否为倒序,须有序
* @Author 李
* @MethodName isReverse
* @Date 19:06 2021/6/4
* @param list
* @return int
* @exception
**/
@SuppressWarnings("unchecked")
private static <T> Boolean isReverse(List<? extends Comparable<? super T>> list){
if (CollectionUtils.isEmpty(list)){
throw new MyException(10000,"列表为空");
}
int inter = list.get(0).compareTo((T)list.get(list.size()-1));
return inter > 0;
}
/**
*
* 功能描述:从迭代器中获取指定对象
* @Author 李
* @MethodName get
* @Date 10:37 2021/6/5
* @param i 迭代器对象
* @param index 索引
* @return T
* @exception
**/
private static <T> T getIterator(ListIterator<? extends T> i, int index) {
T obj;
int pos = i.nextIndex();
if (pos <= index) {
do {
obj = i.next();
} while (pos++ < index);
} else {
do {
obj = i.previous();
} while (--pos > index);
}
return obj;
}