import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Mytest {
public static void main(String... args) {
searchperson();
}
private static void searchperson() {
List<Person> personList = new ArrayList<>();
for (int i = 1; i < 6; i++) {
Person p = new Person(String.valueOf(i), String.valueOf(i), i);
personList.add(p);
}
Comparator<Person> sortComp = new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return p1.getAge() < p2.getAge() ? 1 : -1;
}
};
Comparator<Person> searchComp = new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return String.valueOf(p1.getAge()).compareTo(String.valueOf(p2.getAge()));
}
};
Collections.sort(personList, sortComp);
Person p = new Person("2", "2", 2);
int indx = Collections.binarySearch(personList, p, searchComp);
System.out.println("index is:" + indx);
}
}
class Person {
String firstName;
String lastName;
int age;
public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public int getAge() {
return this.age;
}
}
此打印索引为:1,这是预期值。
但是,当我稍微更改排序逻辑(即)而不是p1.getAge() > p2.getAge()
时,我只是将其更改为p1.getAge() < p2.getAge()
Comparator<Person> sortComp = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() < p2.getAge() ? 1 : -1;
}
}
二进制搜索返回-1。
我得到的索引是:-1
当我反向排序时,我无法理解程序返回-1。有想法吗?
答案 0 :(得分:1)
在Javadoc中查找binarySearch():
*“在进行此调用之前,必须根据指定的比较器(通过sort(List,Comparator)方法)将列表按升序排序。如果未排序,则结果不确定。>
...
返回: 搜索关键字的索引(如果包含在列表中);否则,((插入点)-1)。插入点定义为将键插入列表的点:第一个元素的索引大于键的索引,或者如果列表中的所有元素都为list.size()小于指定的键。请注意,这保证了当且仅当找到密钥时,返回值才> = 0。
由于一旦您更新比较器后,您的列表将按降序排序,则搜索算法会在错误的方向上“搜索”:
伪
1)在“ 3”上搜索“土地”
2)评估2个compareTo 3
3)将搜索范围移到列表的左半部分(期望较小的数字在3的左侧)。
4)在“ 4”上搜索“土地”
5)评估2个compareTo 4个
6)未定义结果,列表似乎是无序的,因为在原始数字的左侧发现了一个较大的数字。
一旦发生这种情况,binarySearch的行为就好像该元素根本不在列表中。在这种情况下,它将返回(-(插入点)-1)。此处的插入点将被定义为索引0,因为第一个发现的值大于搜索的键的值是“ 5” @索引0:
index = (-(0) - 1)
index = 0 - 1
index = -1
答案 1 :(得分:1)
Binary Search
的工作前提是必须根据实现Comparator
的方式来增加集合。换句话说,如果您使用Comparator
以升序排序,则必须使用相同的Comparator
进行搜索,类似地,如果您将Comparator
反向,则必须对集合进行反向排序订购。因此,在您的情况下:
Collections.sort(personList, sortComp); // Collection is sorted in ascending order (p1 > p2)
Person p = new Person("2", "2", 2);
int indx = Collections.binarySearch(personList, p, searchComp); // Search with (p1 > p2)
System.out.println("index is:" + indx);
您正在按升序对集合进行排序(例如p1> p2),然后使用相同的比较器进行搜索,因此它可以工作。反转排序的那一刻,现在搜索将把集合减半,并在上半部分寻找更高的值。由于集合的顺序相反,因此不会找到任何集合并返回-1。
另一方面,在实现compare(a,b)
时,该函数需要返回:
因此,您可以p1.getAge() < p2.getAge() ? 1 : -1;
来代替p1.getAge() - p2.getAge();
如果您使用的是 Java8 + ,则可以将searchPerson
方法简化为:
private static void searchperson() {
List<Person> personList = new ArrayList<>();
for (int i = 1; i < 6; i++) {
Person p = new Person(String.valueOf(i), String.valueOf(i), i);
personList.add(p);
}
Collections.sort(personList, Comparator.comparingInt(Person::getAge));
Person p = new Person("2", "2", 2);
int indx = Collections.binarySearch(personList, p, Comparator.comparingInt(Person::getAge));
System.out.println("index is:" + indx);
}