001/* 002 * Copyright (C) 2016 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.collect; 018 019import static com.google.common.base.Preconditions.checkNotNull; 020 021import com.google.common.annotations.Beta; 022import com.google.common.annotations.GwtCompatible; 023import java.util.Comparator; 024import java.util.Iterator; 025 026/** 027 * Provides static methods for working with {@link Comparator} instances. For many other helpful 028 * comparator utilities, see either {@code Comparator} itself (for Java 8 or later), or {@code 029 * com.google.common.collect.Ordering} (otherwise). 030 * 031 * <h3>Relationship to {@code Ordering}</h3> 032 * 033 * <p>In light of the significant enhancements to {@code Comparator} in Java 8, the overwhelming 034 * majority of usages of {@code Ordering} can be written using only built-in JDK APIs. This class is 035 * intended to "fill the gap" and provide those features of {@code Ordering} not already provided by 036 * the JDK. 037 * 038 * @since 21.0 039 * @author Louis Wasserman 040 */ 041@Beta 042@GwtCompatible 043public final class Comparators { 044 private Comparators() {} 045 046 /** 047 * Returns a new comparator which sorts iterables by comparing corresponding elements pairwise 048 * until a nonzero result is found; imposes "dictionary order." If the end of one iterable is 049 * reached, but not the other, the shorter iterable is considered to be less than the longer one. 050 * For example, a lexicographical natural ordering over integers considers {@code [] < [1] < [1, 051 * 1] < [1, 2] < [2]}. 052 * 053 * <p>Note that {@code Collections.reverseOrder(lexicographical(comparator))} is not equivalent to 054 * {@code lexicographical(Collections.reverseOrder(comparator))} (consider how each would order 055 * {@code [1]} and {@code [1, 1]}). 056 */ 057 // Note: 90% of the time we don't add type parameters or wildcards that serve only to "tweak" the 058 // desired return type. However, *nested* generics introduce a special class of problems that we 059 // think tip it over into being worthwhile. 060 public static <T, S extends T> Comparator<Iterable<S>> lexicographical(Comparator<T> comparator) { 061 return new LexicographicalOrdering<S>(checkNotNull(comparator)); 062 } 063 064 /** 065 * Returns {@code true} if each element in {@code iterable} after the first is greater than or 066 * equal to the element that preceded it, according to the specified comparator. Note that this is 067 * always true when the iterable has fewer than two elements. 068 */ 069 public static <T> boolean isInOrder(Iterable<? extends T> iterable, Comparator<T> comparator) { 070 checkNotNull(comparator); 071 Iterator<? extends T> it = iterable.iterator(); 072 if (it.hasNext()) { 073 T prev = it.next(); 074 while (it.hasNext()) { 075 T next = it.next(); 076 if (comparator.compare(prev, next) > 0) { 077 return false; 078 } 079 prev = next; 080 } 081 } 082 return true; 083 } 084 085 /** 086 * Returns {@code true} if each element in {@code iterable} after the first is <i>strictly</i> 087 * greater than the element that preceded it, according to the specified comparator. Note that 088 * this is always true when the iterable has fewer than two elements. 089 */ 090 public static <T> boolean isInStrictOrder( 091 Iterable<? extends T> iterable, Comparator<T> comparator) { 092 checkNotNull(comparator); 093 Iterator<? extends T> it = iterable.iterator(); 094 if (it.hasNext()) { 095 T prev = it.next(); 096 while (it.hasNext()) { 097 T next = it.next(); 098 if (comparator.compare(prev, next) >= 0) { 099 return false; 100 } 101 prev = next; 102 } 103 } 104 return true; 105 } 106}