Coverage Summary for Class: SortedLists (com.google.common.collect)

Class Method, % Line, %
SortedLists 0% (0/5) 0% (0/27)
SortedLists$KeyAbsentBehavior 0% (0/1) 0% (0/4)
SortedLists$KeyAbsentBehavior$1 0% (0/2) 0% (0/2)
SortedLists$KeyAbsentBehavior$2 0% (0/2) 0% (0/2)
SortedLists$KeyAbsentBehavior$3 0% (0/2) 0% (0/2)
SortedLists$KeyPresentBehavior 0% (0/1) 0% (0/6)
SortedLists$KeyPresentBehavior$1 0% (0/2) 0% (0/2)
SortedLists$KeyPresentBehavior$2 0% (0/2) 0% (0/11)
SortedLists$KeyPresentBehavior$3 0% (0/2) 0% (0/11)
SortedLists$KeyPresentBehavior$4 0% (0/2) 0% (0/2)
SortedLists$KeyPresentBehavior$5 0% (0/2) 0% (0/2)
Total 0% (0/23) 0% (0/71)


1 /* 2  * Copyright (C) 2010 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5  * in compliance with the License. You may obtain a copy of the License at 6  * 7  * http://www.apache.org/licenses/LICENSE-2.0 8  * 9  * Unless required by applicable law or agreed to in writing, software distributed under the License 10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11  * or implied. See the License for the specific language governing permissions and limitations under 12  * the License. 13  */ 14  15 package com.google.common.collect; 16  17 import static com.google.common.base.Preconditions.checkNotNull; 18  19 import com.google.common.annotations.Beta; 20 import com.google.common.annotations.GwtCompatible; 21 import com.google.common.base.Function; 22 import java.util.Collections; 23 import java.util.Comparator; 24 import java.util.List; 25 import java.util.RandomAccess; 26 import org.checkerframework.checker.nullness.qual.Nullable; 27  28 /** 29  * Static methods pertaining to sorted {@link List} instances. 30  * 31  * <p>In this documentation, the terms <i>greatest</i>, <i>greater</i>, <i>least</i>, and 32  * <i>lesser</i> are considered to refer to the comparator on the elements, and the terms 33  * <i>first</i> and <i>last</i> are considered to refer to the elements' ordering in a list. 34  * 35  * @author Louis Wasserman 36  */ 37 @GwtCompatible 38 @Beta 39 final class SortedLists { 40  private SortedLists() {} 41  42  /** 43  * A specification for which index to return if the list contains at least one element that 44  * compares as equal to the key. 45  */ 46  enum KeyPresentBehavior { 47  /** 48  * Return the index of any list element that compares as equal to the key. No guarantees are 49  * made as to which index is returned, if more than one element compares as equal to the key. 50  */ 51  ANY_PRESENT { 52  @Override 53  <E> int resultIndex( 54  Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex) { 55  return foundIndex; 56  } 57  }, 58  /** Return the index of the last list element that compares as equal to the key. */ 59  LAST_PRESENT { 60  @Override 61  <E> int resultIndex( 62  Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex) { 63  // Of course, we have to use binary search to find the precise 64  // breakpoint... 65  int lower = foundIndex; 66  int upper = list.size() - 1; 67  // Everything between lower and upper inclusive compares at >= 0. 68  while (lower < upper) { 69  int middle = (lower + upper + 1) >>> 1; 70  int c = comparator.compare(list.get(middle), key); 71  if (c > 0) { 72  upper = middle - 1; 73  } else { // c == 0 74  lower = middle; 75  } 76  } 77  return lower; 78  } 79  }, 80  /** Return the index of the first list element that compares as equal to the key. */ 81  FIRST_PRESENT { 82  @Override 83  <E> int resultIndex( 84  Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex) { 85  // Of course, we have to use binary search to find the precise 86  // breakpoint... 87  int lower = 0; 88  int upper = foundIndex; 89  // Of course, we have to use binary search to find the precise breakpoint... 90  // Everything between lower and upper inclusive compares at <= 0. 91  while (lower < upper) { 92  int middle = (lower + upper) >>> 1; 93  int c = comparator.compare(list.get(middle), key); 94  if (c < 0) { 95  lower = middle + 1; 96  } else { // c == 0 97  upper = middle; 98  } 99  } 100  return lower; 101  } 102  }, 103  /** 104  * Return the index of the first list element that compares as greater than the key, or {@code 105  * list.size()} if there is no such element. 106  */ 107  FIRST_AFTER { 108  @Override 109  public <E> int resultIndex( 110  Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex) { 111  return LAST_PRESENT.resultIndex(comparator, key, list, foundIndex) + 1; 112  } 113  }, 114  /** 115  * Return the index of the last list element that compares as less than the key, or {@code -1} 116  * if there is no such element. 117  */ 118  LAST_BEFORE { 119  @Override 120  public <E> int resultIndex( 121  Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex) { 122  return FIRST_PRESENT.resultIndex(comparator, key, list, foundIndex) - 1; 123  } 124  }; 125  126  abstract <E> int resultIndex( 127  Comparator<? super E> comparator, E key, List<? extends E> list, int foundIndex); 128  } 129  130  /** 131  * A specification for which index to return if the list contains no elements that compare as 132  * equal to the key. 133  */ 134  enum KeyAbsentBehavior { 135  /** 136  * Return the index of the next lower element in the list, or {@code -1} if there is no such 137  * element. 138  */ 139  NEXT_LOWER { 140  @Override 141  int resultIndex(int higherIndex) { 142  return higherIndex - 1; 143  } 144  }, 145  /** 146  * Return the index of the next higher element in the list, or {@code list.size()} if there is 147  * no such element. 148  */ 149  NEXT_HIGHER { 150  @Override 151  public int resultIndex(int higherIndex) { 152  return higherIndex; 153  } 154  }, 155  /** 156  * Return {@code ~insertionIndex}, where {@code insertionIndex} is defined as the point at which 157  * the key would be inserted into the list: the index of the next higher element in the list, or 158  * {@code list.size()} if there is no such element. 159  * 160  * <p>Note that the return value will be {@code >= 0} if and only if there is an element of the 161  * list that compares as equal to the key. 162  * 163  * <p>This is equivalent to the behavior of {@link java.util.Collections#binarySearch(List, 164  * Object)} when the key isn't present, since {@code ~insertionIndex} is equal to {@code -1 - 165  * insertionIndex}. 166  */ 167  INVERTED_INSERTION_INDEX { 168  @Override 169  public int resultIndex(int higherIndex) { 170  return ~higherIndex; 171  } 172  }; 173  174  abstract int resultIndex(int higherIndex); 175  } 176  177  /** 178  * Searches the specified naturally ordered list for the specified object using the binary search 179  * algorithm. 180  * 181  * <p>Equivalent to {@link #binarySearch(List, Function, Object, Comparator, KeyPresentBehavior, 182  * KeyAbsentBehavior)} using {@link Ordering#natural}. 183  */ 184  public static <E extends Comparable> int binarySearch( 185  List<? extends E> list, 186  E e, 187  KeyPresentBehavior presentBehavior, 188  KeyAbsentBehavior absentBehavior) { 189  checkNotNull(e); 190  return binarySearch(list, e, Ordering.natural(), presentBehavior, absentBehavior); 191  } 192  193  /** 194  * Binary searches the list for the specified key, using the specified key function. 195  * 196  * <p>Equivalent to {@link #binarySearch(List, Function, Object, Comparator, KeyPresentBehavior, 197  * KeyAbsentBehavior)} using {@link Ordering#natural}. 198  */ 199  public static <E, K extends Comparable> int binarySearch( 200  List<E> list, 201  Function<? super E, K> keyFunction, 202  @Nullable K key, 203  KeyPresentBehavior presentBehavior, 204  KeyAbsentBehavior absentBehavior) { 205  return binarySearch( 206  list, keyFunction, key, Ordering.natural(), presentBehavior, absentBehavior); 207  } 208  209  /** 210  * Binary searches the list for the specified key, using the specified key function. 211  * 212  * <p>Equivalent to {@link #binarySearch(List, Object, Comparator, KeyPresentBehavior, 213  * KeyAbsentBehavior)} using {@link Lists#transform(List, Function) Lists.transform(list, 214  * keyFunction)}. 215  */ 216  public static <E, K> int binarySearch( 217  List<E> list, 218  Function<? super E, K> keyFunction, 219  @Nullable K key, 220  Comparator<? super K> keyComparator, 221  KeyPresentBehavior presentBehavior, 222  KeyAbsentBehavior absentBehavior) { 223  return binarySearch( 224  Lists.transform(list, keyFunction), key, keyComparator, presentBehavior, absentBehavior); 225  } 226  227  /** 228  * Searches the specified list for the specified object using the binary search algorithm. The 229  * list must be sorted into ascending order according to the specified comparator (as by the 230  * {@link Collections#sort(List, Comparator) Collections.sort(List, Comparator)} method), prior to 231  * making this call. If it is not sorted, the results are undefined. 232  * 233  * <p>If there are elements in the list which compare as equal to the key, the choice of {@link 234  * KeyPresentBehavior} decides which index is returned. If no elements compare as equal to the 235  * key, the choice of {@link KeyAbsentBehavior} decides which index is returned. 236  * 237  * <p>This method runs in log(n) time on random-access lists, which offer near-constant-time 238  * access to each list element. 239  * 240  * @param list the list to be searched. 241  * @param key the value to be searched for. 242  * @param comparator the comparator by which the list is ordered. 243  * @param presentBehavior the specification for what to do if at least one element of the list 244  * compares as equal to the key. 245  * @param absentBehavior the specification for what to do if no elements of the list compare as 246  * equal to the key. 247  * @return the index determined by the {@code KeyPresentBehavior}, if the key is in the list; 248  * otherwise the index determined by the {@code KeyAbsentBehavior}. 249  */ 250  public static <E> int binarySearch( 251  List<? extends E> list, 252  @Nullable E key, 253  Comparator<? super E> comparator, 254  KeyPresentBehavior presentBehavior, 255  KeyAbsentBehavior absentBehavior) { 256  checkNotNull(comparator); 257  checkNotNull(list); 258  checkNotNull(presentBehavior); 259  checkNotNull(absentBehavior); 260  if (!(list instanceof RandomAccess)) { 261  list = Lists.newArrayList(list); 262  } 263  // TODO(lowasser): benchmark when it's best to do a linear search 264  265  int lower = 0; 266  int upper = list.size() - 1; 267  268  while (lower <= upper) { 269  int middle = (lower + upper) >>> 1; 270  int c = comparator.compare(key, list.get(middle)); 271  if (c < 0) { 272  upper = middle - 1; 273  } else if (c > 0) { 274  lower = middle + 1; 275  } else { 276  return lower 277  + presentBehavior.resultIndex( 278  comparator, key, list.subList(lower, upper + 1), middle - lower); 279  } 280  } 281  return absentBehavior.resultIndex(lower); 282  } 283 }