1

Consider the following code .

  List<Integer> list = new Random().ints(10,1,50).boxed().collect(Collectors.toList());
        list.sort(Comparator.naturalOrder());
        System.out.println(list);
        System.out.print("Enter key :");
        Scanner sc = new Scanner(System.in);
        int key = sc.nextInt();
        int ans = Collections.binarySearch(list, key);

        String result = String.format("ans = %d, list.at(ans*-1) = %d , lower bond = %d , upper bound = %d ", ans,list.get(ans*-1),list.get(ans*-1 -2 ) , 
                list.get(ans * -1 -1));
        System.out.println(result);

I was working on binarySearch method given by Collections class. When key does not present in list, it gives these weird numbers in negative. I mapped them to their lower bound and upper bound. I worked on several examples and always got it right.

see this

screenshot

For every input I have given it return correct upper bound and lower bound inside the list. Can Anyone explain to me ? Whats happening inside the hood ?

  • 1
    Did you ever consider reading [the documentation](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#binarySearch-java.util.List-T-)? – Holger May 24 '20 at 10:43

1 Answers1

2

This is the correct and documented behavior of the Collections.binarySearch. From the JavaDoc:

the index of the search key, if it is contained in the list; otherwise, (-(insertion point) - 1). The insertion point is defined as the point at which the key would be inserted into the list: the index of the first element greater than the key, or list.size() if all elements in the list are less than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the key is found.

Note the last sentence (emphasized by myself), that there is guaranteed the return value is 0 or positive if the key is found. This implies that a negative value is returned if the required element is not present in the input List.


Edit: The negative value is actually not that unpredictable as it looks like. Browsing the source code of java.util.Collections and its private methods calculating the result ...

  • Collections.indexedBinarySearch from the line 278
  • Collections.iteratorBinarySearch from the line 298

... both of them return the following in case the key was not found:

return -(low + 1);  // key not found

Therefore the returned value is the negative index of where the searched element was expected to be located at.

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • 1
    It's funny that you cite a documentation which says that the negative value is `(-(insertion point) - 1)`, right in the first sentence and then, have to browse the source code to find that it is `-(low + 1)` (which is identical to `-low - 1`)... – Holger May 24 '20 at 10:47
  • Although I am having some trust issues in JavaDoc, I believe the algorithm calculation results `low` in `insertion point`. – Nikolas Charalambidis May 24 '20 at 11:18
  • 1
    I don't understand what you mean with "trust issues in JavaDoc". This documentation is the method's specification. If the method did something different, the implementation was broken. But you can trust a widely used 22 year old implementation to do what has been specified. – Holger May 24 '20 at 11:28