如果数组已经排好序了,就可以使用 Arrays.binarySearch()执行快速查找。千万不要对
未排序的数组使用binarySearch(),否则结果不可预料。下面的例子使用
RandIntGenerator填充数组,再用此生成器生成一个值用来测试查找:
//:c11:ArraySearching.java
// UsingArrays.binarySearch().
import com.bruceeckel.util.*;
import java.util.*;
public class ArraySearching {
public static void main(String[] args) {
int[] a = new int[100];
Arrays2.RandIntGenerator gen =
new Arrays2.RandIntGenerator(1000);
Arrays2.fill(a, gen);
Arrays.sort(a);
System.out.println(
"Sortedarray: " +Arrays2.toString(a));
while(true) {
int r = gen.next();
int location = Arrays.binarySearch(a, r);
if(location >= 0) {
System.out.println("Location of " + r +
" is" + location + ", a[" +
location + "] = " + a[location]);
break; // Out of while loop
}
}
}
} ///:~
在 while 循环中随机生成一些值,作为查找的对象,直到找到一个才停止循环。
如果找到了目标,Arrays.binarySearch()的返回值等于或大于 0。否则,返回负值,表
示为了保持数组的排序状态,此目标元素应该插入的位置。这个负值的计算方式是:
-(插入点) - 1
“插入点”是指,第一个大于查找对象的元素在数组中的位置,如果数组所有的元素都小
于要查找的对象,“插入点”就等于 a.size()。
如果数组包含重复的元素,则无法保证找到的是哪一个。此算法并不是为包含重复元素的
数组专门设计的,不过仍然可用。如果你需要对没有重复元素的数组排序,可以使用(保
持排序顺序的)TreeSet,或者(保持插入顺序的)LinkedHashSet,后面我们将会学习
它们。这些类会自动处理所有的细节。除非它们成为程序性能的瓶颈,否则你都不应该自
己维护数组。
如果使用Comparator 排序某个对象数组(基本类型数组无法使用 Comparator 进行排
序),在使用binarySearch()时必须提供同样的 Comparator(使用此方法的重载版本)。
例如,修改AlphabeticSorting.java程序做这种查询:
//:c11:AlphabeticSearch.java
// Searchingwith a Comparator.
import com.bruceeckel.simpletest.*;
import com.bruceeckel.util.*;
import java.util.*;
public class AlphabeticSearch {
private static Test monitor = new Test();
public static void main(String[] args) {
String[] sa = new String[30];
Arrays2.fill(sa, new Arrays2.RandStringGenerator(5));
AlphabeticComparator comp = new AlphabeticComparator();
Arrays.sort(sa, comp);
int index = Arrays.binarySearch(sa,sa[10], comp);
System.out.println("Index = " + index);
monitor.expect(new String[] {
"Index =10"
});
}
} ///:~
这里的 Comparator 必须传递给重载过的 binarySearch(),作为其第三个参数。在这个
例子中,由于要查找的目标就是从数组中选出来的元素,所以肯定能查找到。