Using multiple comparators in java binary search

How to use multiple comparators in binarySearch in java ... I am trying to sort a list of members sorted by name and their starting number.

The problem is that if two participants have the same name, I get an IndexOutOfBoundsException, so I want to do a secondary binary search using the starting number (which is unique), but still keeping them in the correct order with the names.

Here is what I got right now:

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); 
+4
source share
2 answers

Only one comparator

Do not use two comparators, use one comparator that compares both values:

 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; } 

(In your case, bar () is the name, and baz () is the number).

Use libraries

Creating comparators this way is a lot easier if you use Guava or Commons / Lang

Guava Versions:

 @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 Version:

 @Override public int compare(final Foo a, final Foo b){ return new CompareToBuilder() .append(a.bar(), b.bar()) .append(a.baz(), b.baz()) .toComparison(); } 

(Both of these versions will not fail if either of the values ​​is null, my quick and dirty code above will be)

Solve the problem

I don’t think you should do a binary search first, it seems very complicated.

Why don't you use TreeSet with a custom comparator ? Or Collections.sort(list, comparator) ? (For both of these parameters, you can use the comparators that I showed earlier).

In addition, you should consider allowing your contestant to implement Comparable<Contestant> . This way you do not need to use an external Comparator . You can use the same logic as above in the compareTo() method, just replace one of the objects with this .

+5
source

You may have already tried this, and this solution may not be available to you, but if you can change your " Contestant " class, you can extend its " java.lang.Comparable " interface and override Comparable#compareTo(Contestant) to take into account both name and starting number. Subsequently, you can use the Collections.binarySearch(Collection<Contestant>, Contestant) method Collections.binarySearch(Collection<Contestant>, Contestant) for your needs.

0
source

Source: https://habr.com/ru/post/1342004/


All Articles