问题
I have created a List where I have kept some strings. But when I am doing binary search within this list, it is returning negative values while the item is in the list.
So far my knowledge positive value will be returned when item in the list. But for some items it is returning negative and for some items positive.
Code:
@Test
public void hello()
{
// List<String> arlst = new ArrayList<String>();
List arlst = new ArrayList();
arlst.add("TP");
arlst.add("PROVIDES");
arlst.add("QUALITY");
arlst.add("TUTORIALS");
arlst.add("Stop");
arlst.add("StopP");
for (Iterator<String> iterator = (Iterator<String>) arlst.iterator();
iterator.hasNext();)
{
Object next = iterator.next();
System.out.println("next : " + next + " >> Search result : "
+ Collections.binarySearch(arlst, next.toString()));
}
}
Output:
next : TP >> Search result : -7
next : PROVIDES >> Search result : -1
next : QUALITY >> Search result : 2
next : TUTORIALS >> Search result : -7
next : Stop >> Search result : 4
next : StopP >> Search result : 5
回答1:
Reason
You receive strange values since your List
is not sorted prior to calling the method, but this is a requirement. Therefore take a look at the methods documentation:
Searches the specified list for the specified object using the binary search algorithm. The list must be sorted into ascending order according to the natural ordering of its elements (as by the sort(List) method) prior to making this call. If it is not sorted, the results are undefined. If the list contains multiple elements equal to the specified object, there is no guarantee which one will be found.
Explanation
In order to understand that requirement you need to understand how binary search works. Here is a small illustration:
The algorithm takes a look at the element in the middle and compares it to the element to search for. If the given needle is less than the middle element it will continue search to the left, else to the right. It will now take a look at the element to the middle of the reduced range and repeat this process until the element was found or the range can't be divided anymore.
If the elements are not sorted prior, the algorithm will very likely traverse to the wrong direction and obviously not find the element.
Solution
The solution is obvious, sort the List
:
Collections.sort(arlst);
Please note that you should not use raw-types. Therefore, write List<String>
instead of just List
. Then your type-casts will become obsolete too.
In complete the code might then look like
// Setup list
List<String> list = new ArrayList<>();
list.add("TP");
list.add("PROVIDES");
list.add("QUALITY");
list.add("TUTORIALS");
list.add("Stop");
list.add("StopP");
// Sort list
Collections.sort(list);
// Iterate all elements and use binary search
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String element = iter.next();
System.out.println("element : " + element
+ " >> Search result : "
+ Collections.binarySearch(list, element));
}
回答2:
List must be sorted to use binarySearch on it.
回答3:
In the API specification:
Searches the specified list for the specified object using the binary search algorithm. The list must be sorted into ascending order according to the natural ordering of its elements (as by the sort(List) method) prior to making this call. If it is not sorted, the results are undefined. If the list contains multiple elements equal to the specified object, there is no guarantee which one will be found
来源:https://stackoverflow.com/questions/48435155/why-is-collections-binarysearch-giving-wrong-results