我认为Collections.binarySearch()
将返回永不返回0,因为比较器中的比较介于两个整数之间,==
操作总是为假,但是运行结果让我失望......有人可以帮助我吗?
public class ObjectCompare {
static Comparator<Integer> com = new Comparator<Integer>(){
public int compare(Integer i, Integer j) {
return i<j?-1:(i==j?0:1);// i thought i==j would never return true
}
};
public static void main(String[] args){
String[] array = {"0","1","2","3","4","5"};
List<Integer> list = new ArrayList<Integer>();
Integer k = new Integer(1);
Integer l = new Integer(1);
System.out.println(k==l); // this return's false
for(String s : array)
list.add(Integer.valueOf(s));
System.out.println(Collections.binarySearch(list,1,com));// this returns 1
}
}
答案 0 :(得分:3)
如果我理解得很好,问题是“为什么binarySearch
实际上在列表中找到了项目,当我的比较器比较实例时?”正确?
嗯,答案很简单:因为实际上它比较了两个相同的实例(引用)。 Integer
类为-128和127(含)之间的值维护一个缓存实例池。当使用这些值之间的参数调用valueOf
时,始终使用此实例池。
您的代码中有2次调用valueOf(1)
(或多或少显式)。
一个在这里:list.add(Integer.valueOf(s));
。对于循环的一次迭代,调用实际上是list.add(Integer.valueOf("1");
在幕后,调用valueOf(int)
。
第二个是:Arrays.binarySearch(array,1,com)
。从文字1
到Integer
实例的装箱操作实际上是通过调用valueOf(int)
来执行的。
答案 1 :(得分:2)
System.out.println(k==l);
这将返回false,因为它们是不同的对象。众所周知,您需要使用equals()
方法来比较两个Integer
对象的值。
return i<j?-1:(i==j?0:1);
这是compare()
方法的return语句。 我不会等于j,除非列表中有两次相同的对象。请注意,compare()
方法在内部由Collections.sort(list, comparator)
方法调用。 binarySearch()
方法不直接调用此方法。
System.out.println(Collections.binarySearch(list,1,com));
返回1,但此处的1表示搜索项找到的索引。如果您的搜索项为3
,则会返回System.out.println(Collections.binarySearch(list,3,com));
。 1
返回的binarySearch()
不是来自compare()
方法。二进制搜索算法将在内部调用equals()
方法,以在搜索期间比较Integer
值。
因此,您认为永远不会满足的i == j
中的compare()
子句与在Integer
列表上执行的实际二进制搜索无关。 / p>
来自Collections.binarySearch(List, searchItem, comparator)
的文档:
使用二进制搜索算法在指定列表中搜索指定的对象。 在进行此调用之前,必须根据指定的比较器(通过sort(List,Comparator)方法)将列表按升序排序。
答案 2 :(得分:2)
使用此
System.out.println(k.equals(l)); // this return's true
而不是
System.out.println(k==l); // this return's false
因为==这比较整数对象的地址而不是值...
return i<j?-1:((i.equals(j))?0:1);// i thought i==j would return true
而不是
return i<j?-1:((i==j)?0:1);// i thought i==j would never return true
答案 3 :(得分:1)
Integer
是int
的盒装变体,即引用类型。您需要使用Integer#equals
方法来测试相等性,因为==
只会测试引用是否相等:
static Comparator<Integer> com = new Comparator<Integer>(){
public int compare(Integer i, Integer j) {
return i < j ? -1 : (i.equals(j) ? 0 : 1);
}
};
修改强>
现在我考虑一下,为Comparator
编写Integer
是没有意义的,因为Integer
已经实现了Comparable<Integer>
。
答案 4 :(得分:1)
我冒昧地重新设计程序以专注于手头的问题:compare()方法中的i == j:
import java.util.Arrays;
import java.util.Comparator;
public class StackOverflow {
static Comparator<Integer> com = new Comparator<Integer>(){
@Override
public int compare(Integer i, Integer j) {
int res = 0;
if(i<j){
res = -1;
} else if(i == j ){
res = 0;
} else {
res = 1;
}
return res;
}
};
public static void main(String[] args){
Integer[] array = {0,1,2,3,4,5};
System.out.println(Arrays.binarySearch(array,1,com));
}
}
如果您调试/单步执行代码,您会看到在将1与1进行比较时,代码进入res = 0.这可能是一个自动装箱的怪癖?也许因为它必须为我自动取消装箱