package newFeatures8;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/*
* public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序(通过 sort(List) 方法)。
如果没有对列表进行排序,则结果是不确定的。如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。
此方法对“随机访问”列表运行 log(n) 次(它提供接近固定时间的位置访问)。如果指定列表没有实现 RandomAccess 接口并且是一个大型列表,
其实ArrayList接口实现了RandomAccess
则此方法将执行基于迭代器的二分搜索,执行 O(n) 次链接遍历和 O(log n) 次元素比较。
参数:
list - 要搜索的列表。
key - 要搜索的键。
返回:
如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。插入点 被定义为将键插入列表的那一点:即第一个大于此键的元素索引;
如果列表中的所有元素都小于指定的键,则为 list.size()。注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。
抛出:
ClassCastException - 如果列表中包含不可相互比较 的元素(例如,字符串和整数),或者搜索键无法与列表的元素进行相互比较。
*/
public class CollectionsDemo {
public static void main(String[] args) {
binarySearchDemo();
}
/**
* @author ljh
* @param nothing
* @return void
* @since 1.2
* @description 但凡使用binarySearch 前提是有序
*/
public static void binarySearchDemo(){
//
List<String> list=new ArrayList<>();
list.add("abcd");//String类本身就是实现了Comparable接口
list.add("kkkkk");
list.add("z");
list.add("zz1");
list.add("zz");
list.add("qq");
list.add("qq");
list.sort(null);//先进行排序 Collections.sort(list);
System.out.println(list);
//int index=Collections.binarySearch(list, "aaaa");
int index=simulateHalfSearch(list, "aaaa");
System.out.println("下标是:"+index);
/*
* 1.8对list 集合新增的方法:
* (1:)default void sort(Comparator<? super E> c)
* (2:)default void forEach(Consumer<? super T> action)
* (3:)default Stream<E> parallelStream()
* (4:)default void replaceAll(UnaryOperator<E> operator)
* (5:)default boolean removeIf(Predicate<? super E> filter)
* (6:)default Spliterator<E> spliterator()
* (7:)default Stream<E> stream()
*/
}
/**
* @author ljh
* @param List<String> list
* @param String key
* @return int
* @description 模拟二分查找实现原理
*/
public static int simulateHalfSearch(List<String> list,String key){
int min=0,mid,max;
max=list.size()-1;
String strMid=null;
while(min<=max){//只要min<=max就可以折半
mid=(min+max)>>1;//相当于/2
strMid=list.get(mid);
int num=strMid.compareTo(key);
if(num>0){//key小于中间值,往左边走,max要变
max=mid-1;
}else if(num<0){//key大于中间值,往;右边走,min要变
min=mid+1;
}else{
return mid;
}
}
return -min-1;//循环都转完了,还没有找到返回 -(插入点)
//为什么要再减1,因为当插入点为0时,-0=0 这样就不能保证找不到key返回负数了
}
/**
*
* @author ljh
* @description 静态内部类</br>
* 按照字符串的长度进行排序,如果字符串长度相同按按照名称排序
*/
static class strLenCompartor implements Comparator<String>{
@Override
public int compare(String s1, String s2) {
int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
//当主要条件相同一定要按照次要条件排序
if (num==0) {
return s1.compareTo(s2);
}
return num;
}
}
}
binarySearch 源码:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)//BINARYSEARCH_THRESHOLD=5000;
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
indexedBinarySearch 源码:
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
}