1010import java .util .Comparator ;
1111import java .util .List ;
1212import java .util .SortedSet ;
13- import java .util .TreeSet ;
13+ import java .util .function . Function ;
1414
1515/**
1616 * Utility for handling {@link java.util.List} types.
@@ -201,8 +201,9 @@ public static <T> List<T> ofVar(T... values) {
201201 * @param <T>
202202 * Item type.
203203 *
204- * @return Index of item in list.
205- * If the item is not in the list, the negative value of the index where it would appear in sorted order.
204+ * @return Index of item in list, within the range.
205+ * If the item is not in the list, then {@code (-(insertion point) - 1)} where the insertion point is
206+ * the index at which the value would be inserted into the list.
206207 */
207208 public static <T extends Comparable <T >> int binarySearch (@ Nonnull List <T > items , @ Nonnull T target ) {
208209 return binarySearch (items , target , 0 , items .size () - 1 );
@@ -221,24 +222,76 @@ public static <T extends Comparable<T>> int binarySearch(@Nonnull List<T> items,
221222 * Item type.
222223 *
223224 * @return Index of item in list, within the range.
224- * If the item is not in the list, the negative value of the index where it would appear in sorted order.
225+ * If the item is not in the list, then {@code (-(insertion point) - 1)} where the insertion point is
226+ * the index at which the value would be inserted into the list.
225227 */
226228 public static <T extends Comparable <T >> int binarySearch (@ Nonnull List <T > items , @ Nonnull T target , int first , int last ) {
227- if (first > last )
228- // Typically yield '-1' but with this, we will have it such that if 'target' is not in the list
229- // then the return value will be the negative value of the index where it would be inserted into
230- // while maintaining sorted order.
231- return (first == 0 && last == -1 ) ? last : -last ;
232- else {
233- int middle = (first + last ) / 2 ;
229+ while (first <= last ) {
230+ int middle = (first + last ) >>> 1 ;
234231 int compResult = target .compareTo (items .get (middle ));
235232 if (compResult == 0 )
236233 return middle ;
237- else if (compResult < 0 )
238- return binarySearch (items , target , first , middle - 1 );
234+ if (compResult < 0 )
235+ last = middle - 1 ;
236+ else
237+ first = middle + 1 ;
238+ }
239+ return (first == 0 && last == -1 ) ? last : -last ;
240+ }
241+
242+ /**
243+ * @param items
244+ * Item list to search in.
245+ * @param target
246+ * Item to search for.
247+ * @param unbox
248+ * Function to unbox B into T.
249+ * @param <B>
250+ * Box type.
251+ * @param <T>
252+ * Item type.
253+ *
254+ * @return Index of item in list, within the range.
255+ * If the item is not in the list, then {@code (-(insertion point) - 1)} where the insertion point is
256+ * the index at which the value would be inserted into the list.
257+ */
258+ public static <B , T extends Comparable <T >> int binaryUnboxingSearch (@ Nonnull List <B > items , @ Nonnull T target , @ Nonnull Function <B , T > unbox ) {
259+ return binaryUnboxingSearch (items , target , unbox , 0 , items .size () - 1 );
260+ }
261+
262+ /**
263+ * @param items
264+ * Item list to search in.
265+ * @param target
266+ * Item to search for.
267+ * @param unbox
268+ * Function to unbox B into T.
269+ * @param first
270+ * Start range.
271+ * @param last
272+ * End range.
273+ * @param <B>
274+ * Box type.
275+ * @param <T>
276+ * Item type.
277+ *
278+ * @return Index of item in list, within the range.
279+ * If the item is not in the list, then {@code (-(insertion point) - 1)} where the insertion point is
280+ * the index at which the value would be inserted into the list.
281+ */
282+ public static <B , T extends Comparable <T >> int binaryUnboxingSearch (@ Nonnull List <B > items , @ Nonnull T target ,
283+ @ Nonnull Function <B , T > unbox , int first , int last ) {
284+ while (first <= last ) {
285+ int middle = (first + last ) >>> 1 ;
286+ int compResult = target .compareTo (unbox .apply (items .get (middle )));
287+ if (compResult == 0 )
288+ return middle ;
289+ if (compResult < 0 )
290+ last = middle - 1 ;
239291 else
240- return binarySearch ( items , target , middle + 1 , last ) ;
292+ first = middle + 1 ;
241293 }
294+ return (first == 0 && last == -1 ) ? last : -last ;
242295 }
243296
244297 /**
0 commit comments