• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.Beta;
22 import com.google.common.annotations.GwtCompatible;
23 
24 import java.util.Iterator;
25 import java.util.NoSuchElementException;
26 
27 /**
28  * Static methods pertaining to {@link Range} instances.  Each of the
29  * {@link Range nine types of ranges} can be constructed with a corresponding
30  * factory method:
31  *
32  * <dl>
33  * <dt>{@code (a..b)}
34  * <dd>{@link #open}
35  * <dt>{@code [a..b]}
36  * <dd>{@link #closed}
37  * <dt>{@code [a..b)}
38  * <dd>{@link #closedOpen}
39  * <dt>{@code (a..b]}
40  * <dd>{@link #openClosed}
41  * <dt>{@code (a..+∞)}
42  * <dd>{@link #greaterThan}
43  * <dt>{@code [a..+∞)}
44  * <dd>{@link #atLeast}
45  * <dt>{@code (-∞..b)}
46  * <dd>{@link #lessThan}
47  * <dt>{@code (-∞..b]}
48  * <dd>{@link #atMost}
49  * <dt>{@code (-∞..+∞)}
50  * <dd>{@link #all}
51  * </dl>
52  *
53  * <p>Additionally, {@link Range} instances can be constructed by passing the
54  * {@link BoundType bound types} explicitly.
55  *
56  * <dl>
57  * <dt>Bounded on both ends
58  * <dd>{@link #range}
59  * <dt>Unbounded on top ({@code (a..+∞)} or {@code (a..+∞)})
60  * <dd>{@link #downTo}
61  * <dt>Unbounded on bottom ({@code (-∞..b)} or {@code (-∞..b]})
62  * <dd>{@link #upTo}
63  * </dl>
64  *
65  * @author Kevin Bourrillion
66  * @author Gregory Kick
67  * @since 10.0
68  */
69 @GwtCompatible
70 @Beta
71 public final class Ranges {
Ranges()72   private Ranges() {}
73 
create( Cut<C> lowerBound, Cut<C> upperBound)74   static <C extends Comparable<?>> Range<C> create(
75       Cut<C> lowerBound, Cut<C> upperBound) {
76     return new Range<C>(lowerBound, upperBound);
77   }
78 
79   /**
80    * Returns a range that contains all values strictly greater than {@code
81    * lower} and strictly less than {@code upper}.
82    *
83    * @throws IllegalArgumentException if {@code lower} is greater than <i>or
84    *     equal to</i> {@code upper}
85    */
open(C lower, C upper)86   public static <C extends Comparable<?>> Range<C> open(C lower, C upper) {
87     return create(Cut.aboveValue(lower), Cut.belowValue(upper));
88   }
89 
90   /**
91    * Returns a range that contains all values greater than or equal to
92    * {@code lower} and less than or equal to {@code upper}.
93    *
94    * @throws IllegalArgumentException if {@code lower} is greater than {@code
95    *     upper}
96    */
closed(C lower, C upper)97   public static <C extends Comparable<?>> Range<C> closed(C lower, C upper) {
98     return create(Cut.belowValue(lower), Cut.aboveValue(upper));
99   }
100 
101   /**
102    * Returns a range that contains all values greater than or equal to
103    * {@code lower} and strictly less than {@code upper}.
104    *
105    * @throws IllegalArgumentException if {@code lower} is greater than {@code
106    *     upper}
107    */
closedOpen( C lower, C upper)108   public static <C extends Comparable<?>> Range<C> closedOpen(
109       C lower, C upper) {
110     return create(Cut.belowValue(lower), Cut.belowValue(upper));
111   }
112 
113   /**
114    * Returns a range that contains all values strictly greater than {@code
115    * lower} and less than or equal to {@code upper}.
116    *
117    * @throws IllegalArgumentException if {@code lower} is greater than {@code
118    *     upper}
119    */
openClosed( C lower, C upper)120   public static <C extends Comparable<?>> Range<C> openClosed(
121       C lower, C upper) {
122     return create(Cut.aboveValue(lower), Cut.aboveValue(upper));
123   }
124 
125   /**
126    * Returns a range that contains any value from {@code lower} to {@code
127    * upper}, where each endpoint may be either inclusive (closed) or exclusive
128    * (open).
129    *
130    * @throws IllegalArgumentException if {@code lower} is greater than {@code
131    *     upper}
132    */
range( C lower, BoundType lowerType, C upper, BoundType upperType)133   public static <C extends Comparable<?>> Range<C> range(
134       C lower, BoundType lowerType, C upper, BoundType upperType) {
135     checkNotNull(lowerType);
136     checkNotNull(upperType);
137 
138     Cut<C> lowerBound = (lowerType == BoundType.OPEN)
139         ? Cut.aboveValue(lower)
140         : Cut.belowValue(lower);
141     Cut<C> upperBound = (upperType == BoundType.OPEN)
142         ? Cut.belowValue(upper)
143         : Cut.aboveValue(upper);
144     return create(lowerBound, upperBound);
145   }
146 
147   /**
148    * Returns a range that contains all values strictly less than {@code
149    * endpoint}.
150    */
lessThan(C endpoint)151   public static <C extends Comparable<?>> Range<C> lessThan(C endpoint) {
152     return create(Cut.<C>belowAll(), Cut.belowValue(endpoint));
153   }
154 
155   /**
156    * Returns a range that contains all values less than or equal to
157    * {@code endpoint}.
158    */
atMost(C endpoint)159   public static <C extends Comparable<?>> Range<C> atMost(C endpoint) {
160     return create(Cut.<C>belowAll(), Cut.aboveValue(endpoint));
161   }
162 
163   /**
164    * Returns a range with no lower bound up to the given endpoint, which may be
165    * either inclusive (closed) or exclusive (open).
166    */
upTo( C endpoint, BoundType boundType)167   public static <C extends Comparable<?>> Range<C> upTo(
168       C endpoint, BoundType boundType) {
169     switch (boundType) {
170       case OPEN:
171         return lessThan(endpoint);
172       case CLOSED:
173         return atMost(endpoint);
174       default:
175         throw new AssertionError();
176     }
177   }
178 
179   /**
180    * Returns a range that contains all values strictly greater than {@code
181    * endpoint}.
182    */
greaterThan(C endpoint)183   public static <C extends Comparable<?>> Range<C> greaterThan(C endpoint) {
184     return create(Cut.aboveValue(endpoint), Cut.<C>aboveAll());
185   }
186 
187   /**
188    * Returns a range that contains all values greater than or equal to
189    * {@code endpoint}.
190    */
atLeast(C endpoint)191   public static <C extends Comparable<?>> Range<C> atLeast(C endpoint) {
192     return create(Cut.belowValue(endpoint), Cut.<C>aboveAll());
193   }
194 
195   /**
196    * Returns a range from the given endpoint, which may be either inclusive
197    * (closed) or exclusive (open), with no upper bound.
198    */
downTo( C endpoint, BoundType boundType)199   public static <C extends Comparable<?>> Range<C> downTo(
200       C endpoint, BoundType boundType) {
201     switch (boundType) {
202       case OPEN:
203         return greaterThan(endpoint);
204       case CLOSED:
205         return atLeast(endpoint);
206       default:
207         throw new AssertionError();
208     }
209   }
210 
211   /** Returns a range that contains every value of type {@code C}. */
all()212   public static <C extends Comparable<?>> Range<C> all() {
213     return create(Cut.<C>belowAll(), Cut.<C>aboveAll());
214   }
215 
216   /**
217    * Returns a range that {@linkplain Range#contains(Comparable) contains} only
218    * the given value. The returned range is {@linkplain BoundType#CLOSED closed}
219    * on both ends.
220    */
singleton(C value)221   public static <C extends Comparable<?>> Range<C> singleton(C value) {
222     return closed(value, value);
223   }
224 
225   /**
226    * Returns the minimal range that
227    * {@linkplain Range#contains(Comparable) contains} all of the given values.
228    * The returned range is {@linkplain BoundType#CLOSED closed} on both ends.
229    *
230    * @throws ClassCastException if the parameters are not <i>mutually
231    *     comparable</i>
232    * @throws NoSuchElementException if {@code values} is empty
233    * @throws NullPointerException if any of {@code values} is null
234    */
encloseAll( Iterable<C> values)235   public static <C extends Comparable<?>> Range<C> encloseAll(
236       Iterable<C> values) {
237     checkNotNull(values);
238     if (values instanceof ContiguousSet) {
239       return ((ContiguousSet<C>) values).range();
240     }
241     Iterator<C> valueIterator = values.iterator();
242     C min = checkNotNull(valueIterator.next());
243     C max = min;
244     while (valueIterator.hasNext()) {
245       C value = checkNotNull(valueIterator.next());
246       min = Ordering.natural().min(min, value);
247       max = Ordering.natural().max(max, value);
248     }
249     return closed(min, max);
250   }
251 }
252