如何在java中的binarySearch中使用多个比较器... 我正在尝试对按名称和起始编号排序的参赛者名单进行排序。
问题是,如果两个参赛者具有相同的名称,我会得到一个IndexOutOfBoundsException,所以我想使用起始编号(这是唯一的)进行二次二进制搜索,但仍然使用名称保持正确的顺序。
这就是我现在所拥有的:
static void add(Contestant c){
int pos = Collections.binarySearch(byName, c, new ConNameCmp());
if (pos >= 0){
pos = Collections.binarySearch(byName, c, new ConStartCmp());
}
byName.add(-pos-1, c);
答案 0 :(得分:5)
不要使用两个比较器,使用比较两个值的单个比较器:
public int compare(Foo a, Foo b){
// compare bar() values first
int result = a.bar().compareTo(b.bar());
// compare baz() values only if bar() values are different
if(result==0){
result = a.baz().compareTo(b.baz());
}
return result;
}
(在你的情况下,bar()是名称,baz()是数字)。
如果您使用Guava或Commons / Lang
,以这种方式创建比较器要容易得多番石榴版本:
@Override
public int compare(final Foo a, final Foo b){
return ComparisonChain
.start()
.compare(a.bar(), b.bar())
.compare(a.baz(), b.baz())
.result();
}
Commons / Lang版本:
@Override
public int compare(final Foo a, final Foo b){
return new CompareToBuilder()
.append(a.bar(), b.bar())
.append(a.baz(), b.baz())
.toComparison();
}
(如果任何值为null,这两个版本都不会失败,我上面的快速和脏代码将会出现)
我认为你不应该首先进行二元搜索,这看起来很复杂。
为什么不使用TreeSet
with a custom comparator?还是Collections.sort(list, comparator)
? (对于这两个选项,您可以使用我之前展示的比较器。)
另外,你应该考虑让你的参赛者实施Comparable<Contestant>
。这样您就不需要使用外部Comparator
。您可以在compareTo()
方法中使用与上述相同的逻辑,只需使用this
替换其中一个对象。
答案 1 :(得分:0)
您可能已经尝试过此操作,但可能无法使用此解决方案,但如果您可以更改“Contestant
”类,则可以扩展“java.lang.Comparable
”界面,覆盖Comparable#compareTo(Contestant)
方法,以便将名称和起始编号都考虑在内。之后,您将能够根据需要使用Collections.binarySearch(Collection<Contestant>, Contestant)
方法。