• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.base.Equivalence;
23 import com.google.common.base.Function;
24 import com.google.common.base.Predicate;
25 import java.io.Serializable;
26 import java.util.Comparator;
27 import java.util.Iterator;
28 import java.util.NoSuchElementException;
29 import java.util.SortedSet;
30 import javax.annotation.CheckForNull;
31 
32 /**
33  * A range (or "interval") defines the <i>boundaries</i> around a contiguous span of values of some
34  * {@code Comparable} type; for example, "integers from 1 to 100 inclusive." Note that it is not
35  * possible to <i>iterate</i> over these contained values. To do so, pass this range instance and an
36  * appropriate {@link DiscreteDomain} to {@link ContiguousSet#create}.
37  *
38  * <h3>Types of ranges</h3>
39  *
40  * <p>Each end of the range may be bounded or unbounded. If bounded, there is an associated
41  * <i>endpoint</i> value, and the range is considered to be either <i>open</i> (does not include the
42  * endpoint) or <i>closed</i> (includes the endpoint) on that side. With three possibilities on each
43  * side, this yields nine basic types of ranges, enumerated below. (Notation: a square bracket
44  * ({@code [ ]}) indicates that the range is closed on that side; a parenthesis ({@code ( )}) means
45  * it is either open or unbounded. The construct {@code {x | statement}} is read "the set of all
46  * <i>x</i> such that <i>statement</i>.")
47  *
48  * <blockquote>
49  *
50  * <table>
51  * <caption>Range Types</caption>
52  * <tr><th>Notation        <th>Definition               <th>Factory method
53  * <tr><td>{@code (a..b)}  <td>{@code {x | a < x < b}}  <td>{@link Range#open open}
54  * <tr><td>{@code [a..b]}  <td>{@code {x | a <= x <= b}}<td>{@link Range#closed closed}
55  * <tr><td>{@code (a..b]}  <td>{@code {x | a < x <= b}} <td>{@link Range#openClosed openClosed}
56  * <tr><td>{@code [a..b)}  <td>{@code {x | a <= x < b}} <td>{@link Range#closedOpen closedOpen}
57  * <tr><td>{@code (a..+∞)} <td>{@code {x | x > a}}      <td>{@link Range#greaterThan greaterThan}
58  * <tr><td>{@code [a..+∞)} <td>{@code {x | x >= a}}     <td>{@link Range#atLeast atLeast}
59  * <tr><td>{@code (-∞..b)} <td>{@code {x | x < b}}      <td>{@link Range#lessThan lessThan}
60  * <tr><td>{@code (-∞..b]} <td>{@code {x | x <= b}}     <td>{@link Range#atMost atMost}
61  * <tr><td>{@code (-∞..+∞)}<td>{@code {x}}              <td>{@link Range#all all}
62  * </table>
63  *
64  * </blockquote>
65  *
66  * <p>When both endpoints exist, the upper endpoint may not be less than the lower. The endpoints
67  * may be equal only if at least one of the bounds is closed:
68  *
69  * <ul>
70  *   <li>{@code [a..a]} : a singleton range
71  *   <li>{@code [a..a); (a..a]} : {@linkplain #isEmpty empty} ranges; also valid
72  *   <li>{@code (a..a)} : <b>invalid</b>; an exception will be thrown
73  * </ul>
74  *
75  * <h3>Warnings</h3>
76  *
77  * <ul>
78  *   <li>Use immutable value types only, if at all possible. If you must use a mutable type, <b>do
79  *       not</b> allow the endpoint instances to mutate after the range is created!
80  *   <li>Your value type's comparison method should be {@linkplain Comparable consistent with
81  *       equals} if at all possible. Otherwise, be aware that concepts used throughout this
82  *       documentation such as "equal", "same", "unique" and so on actually refer to whether {@link
83  *       Comparable#compareTo compareTo} returns zero, not whether {@link Object#equals equals}
84  *       returns {@code true}.
85  *   <li>A class which implements {@code Comparable<UnrelatedType>} is very broken, and will cause
86  *       undefined horrible things to happen in {@code Range}. For now, the Range API does not
87  *       prevent its use, because this would also rule out all ungenerified (pre-JDK1.5) data types.
88  *       <b>This may change in the future.</b>
89  * </ul>
90  *
91  * <h3>Other notes</h3>
92  *
93  * <ul>
94  *   <li>All ranges are shallow-immutable.
95  *   <li>Instances of this type are obtained using the static factory methods in this class.
96  *   <li>Ranges are <i>convex</i>: whenever two values are contained, all values in between them
97  *       must also be contained. More formally, for any {@code c1 <= c2 <= c3} of type {@code C},
98  *       {@code r.contains(c1) && r.contains(c3)} implies {@code r.contains(c2)}). This means that a
99  *       {@code Range<Integer>} can never be used to represent, say, "all <i>prime</i> numbers from
100  *       1 to 100."
101  *   <li>When evaluated as a {@link Predicate}, a range yields the same result as invoking {@link
102  *       #contains}.
103  *   <li>Terminology note: a range {@code a} is said to be the <i>maximal</i> range having property
104  *       <i>P</i> if, for all ranges {@code b} also having property <i>P</i>, {@code a.encloses(b)}.
105  *       Likewise, {@code a} is <i>minimal</i> when {@code b.encloses(a)} for all {@code b} having
106  *       property <i>P</i>. See, for example, the definition of {@link #intersection intersection}.
107  * </ul>
108  *
109  * <h3>Further reading</h3>
110  *
111  * <p>See the Guava User Guide article on <a
112  * href="https://github.com/google/guava/wiki/RangesExplained">{@code Range}</a>.
113  *
114  * @author Kevin Bourrillion
115  * @author Gregory Kick
116  * @since 10.0
117  */
118 @GwtCompatible
119 @SuppressWarnings("rawtypes")
120 @ElementTypesAreNonnullByDefault
121 public final class Range<C extends Comparable> extends RangeGwtSerializationDependencies
122     implements Predicate<C>, Serializable {
123 
124   static class LowerBoundFn implements Function<Range, Cut> {
125     static final LowerBoundFn INSTANCE = new LowerBoundFn();
126 
127     @Override
apply(Range range)128     public Cut apply(Range range) {
129       return range.lowerBound;
130     }
131   }
132 
133   static class UpperBoundFn implements Function<Range, Cut> {
134     static final UpperBoundFn INSTANCE = new UpperBoundFn();
135 
136     @Override
apply(Range range)137     public Cut apply(Range range) {
138       return range.upperBound;
139     }
140   }
141 
142   @SuppressWarnings("unchecked")
lowerBoundFn()143   static <C extends Comparable<?>> Function<Range<C>, Cut<C>> lowerBoundFn() {
144     return (Function) LowerBoundFn.INSTANCE;
145   }
146 
147   @SuppressWarnings("unchecked")
upperBoundFn()148   static <C extends Comparable<?>> Function<Range<C>, Cut<C>> upperBoundFn() {
149     return (Function) UpperBoundFn.INSTANCE;
150   }
151 
rangeLexOrdering()152   static <C extends Comparable<?>> Ordering<Range<C>> rangeLexOrdering() {
153     return (Ordering<Range<C>>) (Ordering) RangeLexOrdering.INSTANCE;
154   }
155 
create(Cut<C> lowerBound, Cut<C> upperBound)156   static <C extends Comparable<?>> Range<C> create(Cut<C> lowerBound, Cut<C> upperBound) {
157     return new Range<C>(lowerBound, upperBound);
158   }
159 
160   /**
161    * Returns a range that contains all values strictly greater than {@code lower} and strictly less
162    * than {@code upper}.
163    *
164    * @throws IllegalArgumentException if {@code lower} is greater than <i>or equal to</i> {@code
165    *     upper}
166    * @throws ClassCastException if {@code lower} and {@code upper} are not mutually comparable
167    * @since 14.0
168    */
open(C lower, C upper)169   public static <C extends Comparable<?>> Range<C> open(C lower, C upper) {
170     return create(Cut.aboveValue(lower), Cut.belowValue(upper));
171   }
172 
173   /**
174    * Returns a range that contains all values greater than or equal to {@code lower} and less than
175    * or equal to {@code upper}.
176    *
177    * @throws IllegalArgumentException if {@code lower} is greater than {@code upper}
178    * @throws ClassCastException if {@code lower} and {@code upper} are not mutually comparable
179    * @since 14.0
180    */
closed(C lower, C upper)181   public static <C extends Comparable<?>> Range<C> closed(C lower, C upper) {
182     return create(Cut.belowValue(lower), Cut.aboveValue(upper));
183   }
184 
185   /**
186    * Returns a range that contains all values greater than or equal to {@code lower} and strictly
187    * less than {@code upper}.
188    *
189    * @throws IllegalArgumentException if {@code lower} is greater than {@code upper}
190    * @throws ClassCastException if {@code lower} and {@code upper} are not mutually comparable
191    * @since 14.0
192    */
closedOpen(C lower, C upper)193   public static <C extends Comparable<?>> Range<C> closedOpen(C lower, C upper) {
194     return create(Cut.belowValue(lower), Cut.belowValue(upper));
195   }
196 
197   /**
198    * Returns a range that contains all values strictly greater than {@code lower} and less than or
199    * equal to {@code upper}.
200    *
201    * @throws IllegalArgumentException if {@code lower} is greater than {@code upper}
202    * @throws ClassCastException if {@code lower} and {@code upper} are not mutually comparable
203    * @since 14.0
204    */
openClosed(C lower, C upper)205   public static <C extends Comparable<?>> Range<C> openClosed(C lower, C upper) {
206     return create(Cut.aboveValue(lower), Cut.aboveValue(upper));
207   }
208 
209   /**
210    * Returns a range that contains any value from {@code lower} to {@code upper}, where each
211    * endpoint may be either inclusive (closed) or exclusive (open).
212    *
213    * @throws IllegalArgumentException if {@code lower} is greater than {@code upper}
214    * @throws ClassCastException if {@code lower} and {@code upper} are not mutually comparable
215    * @since 14.0
216    */
range( C lower, BoundType lowerType, C upper, BoundType upperType)217   public static <C extends Comparable<?>> Range<C> range(
218       C lower, BoundType lowerType, C upper, BoundType upperType) {
219     checkNotNull(lowerType);
220     checkNotNull(upperType);
221 
222     Cut<C> lowerBound =
223         (lowerType == BoundType.OPEN) ? Cut.aboveValue(lower) : Cut.belowValue(lower);
224     Cut<C> upperBound =
225         (upperType == BoundType.OPEN) ? Cut.belowValue(upper) : Cut.aboveValue(upper);
226     return create(lowerBound, upperBound);
227   }
228 
229   /**
230    * Returns a range that contains all values strictly less than {@code endpoint}.
231    *
232    * @since 14.0
233    */
lessThan(C endpoint)234   public static <C extends Comparable<?>> Range<C> lessThan(C endpoint) {
235     return create(Cut.<C>belowAll(), Cut.belowValue(endpoint));
236   }
237 
238   /**
239    * Returns a range that contains all values less than or equal to {@code endpoint}.
240    *
241    * @since 14.0
242    */
atMost(C endpoint)243   public static <C extends Comparable<?>> Range<C> atMost(C endpoint) {
244     return create(Cut.<C>belowAll(), Cut.aboveValue(endpoint));
245   }
246 
247   /**
248    * Returns a range with no lower bound up to the given endpoint, which may be either inclusive
249    * (closed) or exclusive (open).
250    *
251    * @since 14.0
252    */
upTo(C endpoint, BoundType boundType)253   public static <C extends Comparable<?>> Range<C> upTo(C endpoint, BoundType boundType) {
254     switch (boundType) {
255       case OPEN:
256         return lessThan(endpoint);
257       case CLOSED:
258         return atMost(endpoint);
259       default:
260         throw new AssertionError();
261     }
262   }
263 
264   /**
265    * Returns a range that contains all values strictly greater than {@code endpoint}.
266    *
267    * @since 14.0
268    */
greaterThan(C endpoint)269   public static <C extends Comparable<?>> Range<C> greaterThan(C endpoint) {
270     return create(Cut.aboveValue(endpoint), Cut.<C>aboveAll());
271   }
272 
273   /**
274    * Returns a range that contains all values greater than or equal to {@code endpoint}.
275    *
276    * @since 14.0
277    */
atLeast(C endpoint)278   public static <C extends Comparable<?>> Range<C> atLeast(C endpoint) {
279     return create(Cut.belowValue(endpoint), Cut.<C>aboveAll());
280   }
281 
282   /**
283    * Returns a range from the given endpoint, which may be either inclusive (closed) or exclusive
284    * (open), with no upper bound.
285    *
286    * @since 14.0
287    */
downTo(C endpoint, BoundType boundType)288   public static <C extends Comparable<?>> Range<C> downTo(C endpoint, BoundType boundType) {
289     switch (boundType) {
290       case OPEN:
291         return greaterThan(endpoint);
292       case CLOSED:
293         return atLeast(endpoint);
294       default:
295         throw new AssertionError();
296     }
297   }
298 
299   private static final Range<Comparable> ALL = new Range<>(Cut.belowAll(), Cut.aboveAll());
300 
301   /**
302    * Returns a range that contains every value of type {@code C}.
303    *
304    * @since 14.0
305    */
306   @SuppressWarnings("unchecked")
all()307   public static <C extends Comparable<?>> Range<C> all() {
308     return (Range) ALL;
309   }
310 
311   /**
312    * Returns a range that {@linkplain Range#contains(Comparable) contains} only the given value. The
313    * returned range is {@linkplain BoundType#CLOSED closed} on both ends.
314    *
315    * @since 14.0
316    */
singleton(C value)317   public static <C extends Comparable<?>> Range<C> singleton(C value) {
318     return closed(value, value);
319   }
320 
321   /**
322    * Returns the minimal range that {@linkplain Range#contains(Comparable) contains} all of the
323    * given values. The returned range is {@linkplain BoundType#CLOSED closed} on both ends.
324    *
325    * @throws ClassCastException if the values are not mutually comparable
326    * @throws NoSuchElementException if {@code values} is empty
327    * @throws NullPointerException if any of {@code values} is null
328    * @since 14.0
329    */
encloseAll(Iterable<C> values)330   public static <C extends Comparable<?>> Range<C> encloseAll(Iterable<C> values) {
331     checkNotNull(values);
332     if (values instanceof SortedSet) {
333       SortedSet<C> set = (SortedSet<C>) values;
334       Comparator<?> comparator = set.comparator();
335       if (Ordering.natural().equals(comparator) || comparator == null) {
336         return closed(set.first(), set.last());
337       }
338     }
339     Iterator<C> valueIterator = values.iterator();
340     C min = checkNotNull(valueIterator.next());
341     C max = min;
342     while (valueIterator.hasNext()) {
343       C value = checkNotNull(valueIterator.next());
344       min = Ordering.natural().min(min, value);
345       max = Ordering.natural().max(max, value);
346     }
347     return closed(min, max);
348   }
349 
350   final Cut<C> lowerBound;
351   final Cut<C> upperBound;
352 
Range(Cut<C> lowerBound, Cut<C> upperBound)353   private Range(Cut<C> lowerBound, Cut<C> upperBound) {
354     this.lowerBound = checkNotNull(lowerBound);
355     this.upperBound = checkNotNull(upperBound);
356     if (lowerBound.compareTo(upperBound) > 0
357         || lowerBound == Cut.<C>aboveAll()
358         || upperBound == Cut.<C>belowAll()) {
359       throw new IllegalArgumentException("Invalid range: " + toString(lowerBound, upperBound));
360     }
361   }
362 
363   /** Returns {@code true} if this range has a lower endpoint. */
hasLowerBound()364   public boolean hasLowerBound() {
365     return lowerBound != Cut.belowAll();
366   }
367 
368   /**
369    * Returns the lower endpoint of this range.
370    *
371    * @throws IllegalStateException if this range is unbounded below (that is, {@link
372    *     #hasLowerBound()} returns {@code false})
373    */
lowerEndpoint()374   public C lowerEndpoint() {
375     return lowerBound.endpoint();
376   }
377 
378   /**
379    * Returns the type of this range's lower bound: {@link BoundType#CLOSED} if the range includes
380    * its lower endpoint, {@link BoundType#OPEN} if it does not.
381    *
382    * @throws IllegalStateException if this range is unbounded below (that is, {@link
383    *     #hasLowerBound()} returns {@code false})
384    */
lowerBoundType()385   public BoundType lowerBoundType() {
386     return lowerBound.typeAsLowerBound();
387   }
388 
389   /** Returns {@code true} if this range has an upper endpoint. */
hasUpperBound()390   public boolean hasUpperBound() {
391     return upperBound != Cut.aboveAll();
392   }
393 
394   /**
395    * Returns the upper endpoint of this range.
396    *
397    * @throws IllegalStateException if this range is unbounded above (that is, {@link
398    *     #hasUpperBound()} returns {@code false})
399    */
upperEndpoint()400   public C upperEndpoint() {
401     return upperBound.endpoint();
402   }
403 
404   /**
405    * Returns the type of this range's upper bound: {@link BoundType#CLOSED} if the range includes
406    * its upper endpoint, {@link BoundType#OPEN} if it does not.
407    *
408    * @throws IllegalStateException if this range is unbounded above (that is, {@link
409    *     #hasUpperBound()} returns {@code false})
410    */
upperBoundType()411   public BoundType upperBoundType() {
412     return upperBound.typeAsUpperBound();
413   }
414 
415   /**
416    * Returns {@code true} if this range is of the form {@code [v..v)} or {@code (v..v]}. (This does
417    * not encompass ranges of the form {@code (v..v)}, because such ranges are <i>invalid</i> and
418    * can't be constructed at all.)
419    *
420    * <p>Note that certain discrete ranges such as the integer range {@code (3..4)} are <b>not</b>
421    * considered empty, even though they contain no actual values. In these cases, it may be helpful
422    * to preprocess ranges with {@link #canonical(DiscreteDomain)}.
423    */
isEmpty()424   public boolean isEmpty() {
425     return lowerBound.equals(upperBound);
426   }
427 
428   /**
429    * Returns {@code true} if {@code value} is within the bounds of this range. For example, on the
430    * range {@code [0..2)}, {@code contains(1)} returns {@code true}, while {@code contains(2)}
431    * returns {@code false}.
432    */
contains(C value)433   public boolean contains(C value) {
434     checkNotNull(value);
435     // let this throw CCE if there is some trickery going on
436     return lowerBound.isLessThan(value) && !upperBound.isLessThan(value);
437   }
438 
439   /**
440    * @deprecated Provided only to satisfy the {@link Predicate} interface; use {@link #contains}
441    *     instead.
442    */
443   @Deprecated
444   @Override
apply(C input)445   public boolean apply(C input) {
446     return contains(input);
447   }
448 
449   /**
450    * Returns {@code true} if every element in {@code values} is {@linkplain #contains contained} in
451    * this range.
452    */
containsAll(Iterable<? extends C> values)453   public boolean containsAll(Iterable<? extends C> values) {
454     if (Iterables.isEmpty(values)) {
455       return true;
456     }
457 
458     // this optimizes testing equality of two range-backed sets
459     if (values instanceof SortedSet) {
460       SortedSet<? extends C> set = (SortedSet<? extends C>) values;
461       Comparator<?> comparator = set.comparator();
462       if (Ordering.natural().equals(comparator) || comparator == null) {
463         return contains(set.first()) && contains(set.last());
464       }
465     }
466 
467     for (C value : values) {
468       if (!contains(value)) {
469         return false;
470       }
471     }
472     return true;
473   }
474 
475   /**
476    * Returns {@code true} if the bounds of {@code other} do not extend outside the bounds of this
477    * range. Examples:
478    *
479    * <ul>
480    *   <li>{@code [3..6]} encloses {@code [4..5]}
481    *   <li>{@code (3..6)} encloses {@code (3..6)}
482    *   <li>{@code [3..6]} encloses {@code [4..4)} (even though the latter is empty)
483    *   <li>{@code (3..6]} does not enclose {@code [3..6]}
484    *   <li>{@code [4..5]} does not enclose {@code (3..6)} (even though it contains every value
485    *       contained by the latter range)
486    *   <li>{@code [3..6]} does not enclose {@code (1..1]} (even though it contains every value
487    *       contained by the latter range)
488    * </ul>
489    *
490    * <p>Note that if {@code a.encloses(b)}, then {@code b.contains(v)} implies {@code
491    * a.contains(v)}, but as the last two examples illustrate, the converse is not always true.
492    *
493    * <p>Being reflexive, antisymmetric and transitive, the {@code encloses} relation defines a
494    * <i>partial order</i> over ranges. There exists a unique {@linkplain Range#all maximal} range
495    * according to this relation, and also numerous {@linkplain #isEmpty minimal} ranges. Enclosure
496    * also implies {@linkplain #isConnected connectedness}.
497    */
encloses(Range<C> other)498   public boolean encloses(Range<C> other) {
499     return lowerBound.compareTo(other.lowerBound) <= 0
500         && upperBound.compareTo(other.upperBound) >= 0;
501   }
502 
503   /**
504    * Returns {@code true} if there exists a (possibly empty) range which is {@linkplain #encloses
505    * enclosed} by both this range and {@code other}.
506    *
507    * <p>For example,
508    *
509    * <ul>
510    *   <li>{@code [2, 4)} and {@code [5, 7)} are not connected
511    *   <li>{@code [2, 4)} and {@code [3, 5)} are connected, because both enclose {@code [3, 4)}
512    *   <li>{@code [2, 4)} and {@code [4, 6)} are connected, because both enclose the empty range
513    *       {@code [4, 4)}
514    * </ul>
515    *
516    * <p>Note that this range and {@code other} have a well-defined {@linkplain #span union} and
517    * {@linkplain #intersection intersection} (as a single, possibly-empty range) if and only if this
518    * method returns {@code true}.
519    *
520    * <p>The connectedness relation is both reflexive and symmetric, but does not form an {@linkplain
521    * Equivalence equivalence relation} as it is not transitive.
522    *
523    * <p>Note that certain discrete ranges are not considered connected, even though there are no
524    * elements "between them." For example, {@code [3, 5]} is not considered connected to {@code [6,
525    * 10]}. In these cases, it may be desirable for both input ranges to be preprocessed with {@link
526    * #canonical(DiscreteDomain)} before testing for connectedness.
527    */
isConnected(Range<C> other)528   public boolean isConnected(Range<C> other) {
529     return lowerBound.compareTo(other.upperBound) <= 0
530         && other.lowerBound.compareTo(upperBound) <= 0;
531   }
532 
533   /**
534    * Returns the maximal range {@linkplain #encloses enclosed} by both this range and {@code
535    * connectedRange}, if such a range exists.
536    *
537    * <p>For example, the intersection of {@code [1..5]} and {@code (3..7)} is {@code (3..5]}. The
538    * resulting range may be empty; for example, {@code [1..5)} intersected with {@code [5..7)}
539    * yields the empty range {@code [5..5)}.
540    *
541    * <p>The intersection exists if and only if the two ranges are {@linkplain #isConnected
542    * connected}.
543    *
544    * <p>The intersection operation is commutative, associative and idempotent, and its identity
545    * element is {@link Range#all}).
546    *
547    * @throws IllegalArgumentException if {@code isConnected(connectedRange)} is {@code false}
548    */
intersection(Range<C> connectedRange)549   public Range<C> intersection(Range<C> connectedRange) {
550     int lowerCmp = lowerBound.compareTo(connectedRange.lowerBound);
551     int upperCmp = upperBound.compareTo(connectedRange.upperBound);
552     if (lowerCmp >= 0 && upperCmp <= 0) {
553       return this;
554     } else if (lowerCmp <= 0 && upperCmp >= 0) {
555       return connectedRange;
556     } else {
557       Cut<C> newLower = (lowerCmp >= 0) ? lowerBound : connectedRange.lowerBound;
558       Cut<C> newUpper = (upperCmp <= 0) ? upperBound : connectedRange.upperBound;
559       return create(newLower, newUpper);
560     }
561   }
562 
563   /**
564    * Returns the maximal range lying between this range and {@code otherRange}, if such a range
565    * exists. The resulting range may be empty if the two ranges are adjacent but non-overlapping.
566    *
567    * <p>For example, the gap of {@code [1..5]} and {@code (7..10)} is {@code (5..7]}. The resulting
568    * range may be empty; for example, the gap between {@code [1..5)} {@code [5..7)} yields the empty
569    * range {@code [5..5)}.
570    *
571    * <p>The gap exists if and only if the two ranges are either disconnected or immediately adjacent
572    * (any intersection must be an empty range).
573    *
574    * <p>The gap operation is commutative.
575    *
576    * @throws IllegalArgumentException if this range and {@code otherRange} have a nonempty
577    *     intersection
578    * @since 27.0
579    */
gap(Range<C> otherRange)580   public Range<C> gap(Range<C> otherRange) {
581     /*
582      * For an explanation of the basic principle behind this check, see
583      * https://stackoverflow.com/a/35754308/28465
584      *
585      * In that explanation's notation, our `overlap` check would be `x1 < y2 && y1 < x2`. We've
586      * flipped one part of the check so that we're using "less than" in both cases (rather than a
587      * mix of "less than" and "greater than"). We've also switched to "strictly less than" rather
588      * than "less than or equal to" because of *handwave* the difference between "endpoints of
589      * inclusive ranges" and "Cuts."
590      */
591     if (lowerBound.compareTo(otherRange.upperBound) < 0
592         && otherRange.lowerBound.compareTo(upperBound) < 0) {
593       throw new IllegalArgumentException(
594           "Ranges have a nonempty intersection: " + this + ", " + otherRange);
595     }
596 
597     boolean isThisFirst = this.lowerBound.compareTo(otherRange.lowerBound) < 0;
598     Range<C> firstRange = isThisFirst ? this : otherRange;
599     Range<C> secondRange = isThisFirst ? otherRange : this;
600     return create(firstRange.upperBound, secondRange.lowerBound);
601   }
602 
603   /**
604    * Returns the minimal range that {@linkplain #encloses encloses} both this range and {@code
605    * other}. For example, the span of {@code [1..3]} and {@code (5..7)} is {@code [1..7)}.
606    *
607    * <p><i>If</i> the input ranges are {@linkplain #isConnected connected}, the returned range can
608    * also be called their <i>union</i>. If they are not, note that the span might contain values
609    * that are not contained in either input range.
610    *
611    * <p>Like {@link #intersection(Range) intersection}, this operation is commutative, associative
612    * and idempotent. Unlike it, it is always well-defined for any two input ranges.
613    */
614   public Range<C> span(Range<C> other) {
615     int lowerCmp = lowerBound.compareTo(other.lowerBound);
616     int upperCmp = upperBound.compareTo(other.upperBound);
617     if (lowerCmp <= 0 && upperCmp >= 0) {
618       return this;
619     } else if (lowerCmp >= 0 && upperCmp <= 0) {
620       return other;
621     } else {
622       Cut<C> newLower = (lowerCmp <= 0) ? lowerBound : other.lowerBound;
623       Cut<C> newUpper = (upperCmp >= 0) ? upperBound : other.upperBound;
624       return create(newLower, newUpper);
625     }
626   }
627 
628   /**
629    * Returns the canonical form of this range in the given domain. The canonical form has the
630    * following properties:
631    *
632    * <ul>
633    *   <li>equivalence: {@code a.canonical().contains(v) == a.contains(v)} for all {@code v} (in
634    *       other words, {@code ContiguousSet.create(a.canonical(domain), domain).equals(
635    *       ContiguousSet.create(a, domain))}
636    *   <li>uniqueness: unless {@code a.isEmpty()}, {@code ContiguousSet.create(a,
637    *       domain).equals(ContiguousSet.create(b, domain))} implies {@code
638    *       a.canonical(domain).equals(b.canonical(domain))}
639    *   <li>idempotence: {@code a.canonical(domain).canonical(domain).equals(a.canonical(domain))}
640    * </ul>
641    *
642    * <p>Furthermore, this method guarantees that the range returned will be one of the following
643    * canonical forms:
644    *
645    * <ul>
646    *   <li>[start..end)
647    *   <li>[start..+∞)
648    *   <li>(-∞..end) (only if type {@code C} is unbounded below)
649    *   <li>(-∞..+∞) (only if type {@code C} is unbounded below)
650    * </ul>
651    */
652   public Range<C> canonical(DiscreteDomain<C> domain) {
653     checkNotNull(domain);
654     Cut<C> lower = lowerBound.canonical(domain);
655     Cut<C> upper = upperBound.canonical(domain);
656     return (lower == lowerBound && upper == upperBound) ? this : create(lower, upper);
657   }
658 
659   /**
660    * Returns {@code true} if {@code object} is a range having the same endpoints and bound types as
661    * this range. Note that discrete ranges such as {@code (1..4)} and {@code [2..3]} are <b>not</b>
662    * equal to one another, despite the fact that they each contain precisely the same set of values.
663    * Similarly, empty ranges are not equal unless they have exactly the same representation, so
664    * {@code [3..3)}, {@code (3..3]}, {@code (4..4]} are all unequal.
665    */
666   @Override
667   public boolean equals(@CheckForNull Object object) {
668     if (object instanceof Range) {
669       Range<?> other = (Range<?>) object;
670       return lowerBound.equals(other.lowerBound) && upperBound.equals(other.upperBound);
671     }
672     return false;
673   }
674 
675   /** Returns a hash code for this range. */
676   @Override
677   public int hashCode() {
678     return lowerBound.hashCode() * 31 + upperBound.hashCode();
679   }
680 
681   /**
682    * Returns a string representation of this range, such as {@code "[3..5)"} (other examples are
683    * listed in the class documentation).
684    */
685   @Override
686   public String toString() {
687     return toString(lowerBound, upperBound);
688   }
689 
690   private static String toString(Cut<?> lowerBound, Cut<?> upperBound) {
691     StringBuilder sb = new StringBuilder(16);
692     lowerBound.describeAsLowerBound(sb);
693     sb.append("..");
694     upperBound.describeAsUpperBound(sb);
695     return sb.toString();
696   }
697 
698   Object readResolve() {
699     if (this.equals(ALL)) {
700       return all();
701     } else {
702       return this;
703     }
704   }
705 
706   @SuppressWarnings("unchecked") // this method may throw CCE
707   static int compareOrThrow(Comparable left, Comparable right) {
708     return left.compareTo(right);
709   }
710 
711   /** Needed to serialize sorted collections of Ranges. */
712   private static class RangeLexOrdering extends Ordering<Range<?>> implements Serializable {
713     static final Ordering<Range<?>> INSTANCE = new RangeLexOrdering();
714 
715     @Override
716     public int compare(Range<?> left, Range<?> right) {
717       return ComparisonChain.start()
718           .compare(left.lowerBound, right.lowerBound)
719           .compare(left.upperBound, right.upperBound)
720           .result();
721     }
722 
723     private static final long serialVersionUID = 0;
724   }
725 
726   private static final long serialVersionUID = 0;
727 }
728