ListUtil { @Pure public static <T> int lowerIndex(List<T> list, Comparator<? super T> comparator, T elt) { try { assert comparator != null; assert list != null; if (elt == null) { return -1; } int first = 0; int last = list.size() - 1; while (last >= first) { final int center = (first + last) / 2; final T indata = list.get(center); final int cmp = comparator.compare(elt, indata); if (cmp <= 0) { last = center - 1; } else { first = center + 1; } } return last; } catch (AssertionError e) { throw e; } catch (Throwable exception) { return -1; } } private  ListUtil(); static int remove(List<E> list, Comparator<? super E> comparator, E data); @Inline(value = "add($1, $2, $3, false, false)") static int addIfAbsent(List<E> list, Comparator<? super E> comparator, E data); static int add(List<E> list, Comparator<? super E> comparator, E data,
			boolean allowMultipleOccurencesOfSameValue, boolean allowReplacement); @Pure static boolean contains(List<E> list, Comparator<? super E> comparator, E data); @Pure static int indexOf(List<T> list, Comparator<? super T> comparator, T elt); @Pure static int lastIndexOf(List<T> list, Comparator<? super T> comparator, T elt); @Pure static int getInsertionIndex(List<T> list, Comparator<? super T> comparator, T elt); @Pure static int getInsertionIndex(List<T> list, Comparator<? super T> comparator, T elt, boolean allowMultiple); @Pure static int ceilingIndex(List<T> list, Comparator<? super T> comparator, T elt); @Pure static int floorIndex(List<T> list, Comparator<? super T> comparator, T elt); @Pure static int higherIndex(List<T> list, Comparator<? super T> comparator, T elt); @Pure static int lowerIndex(List<T> list, Comparator<? super T> comparator, T elt); static Iterator<T> reverseIterator(final List<T> list);  }
@Test public void lowerIndexComparatorTList() { List<Integer> list = new ArrayList<>(); list.addAll(Arrays.asList(1, 4, 6, 6, 6, 12, 30)); assertEquals(-1, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), -2)); assertEquals(4, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), 7)); assertEquals(6, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), 34)); assertEquals(-1, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), 1)); assertEquals(0, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), 4)); assertEquals(1, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), 6)); assertEquals(4, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), 12)); assertEquals(5, ListUtil.lowerIndex(list, new NaturalOrderComparator<Integer>(), 30)); Iterator<Integer> iterator = list.iterator(); assertEquals(Integer.valueOf(1), iterator.next()); assertEquals(Integer.valueOf(4), iterator.next()); assertEquals(Integer.valueOf(6), iterator.next()); assertEquals(Integer.valueOf(6), iterator.next()); assertEquals(Integer.valueOf(6), iterator.next()); assertEquals(Integer.valueOf(12), iterator.next()); assertEquals(Integer.valueOf(30), iterator.next()); assertFalse(iterator.hasNext()); }