diff options
Diffstat (limited to 'guava/src/com/google/common/collect/Ranges.java')
-rw-r--r-- | guava/src/com/google/common/collect/Ranges.java | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/guava/src/com/google/common/collect/Ranges.java b/guava/src/com/google/common/collect/Ranges.java new file mode 100644 index 0000000..4062146 --- /dev/null +++ b/guava/src/com/google/common/collect/Ranges.java @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2009 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Static methods pertaining to {@link Range} instances. Each of the + * {@link Range nine types of ranges} can be constructed with a corresponding + * factory method: + * + * <dl> + * <dt>{@code (a..b)} + * <dd>{@link #open} + * <dt>{@code [a..b]} + * <dd>{@link #closed} + * <dt>{@code [a..b)} + * <dd>{@link #closedOpen} + * <dt>{@code (a..b]} + * <dd>{@link #openClosed} + * <dt>{@code (a..+∞)} + * <dd>{@link #greaterThan} + * <dt>{@code [a..+∞)} + * <dd>{@link #atLeast} + * <dt>{@code (-∞..b)} + * <dd>{@link #lessThan} + * <dt>{@code (-∞..b]} + * <dd>{@link #atMost} + * <dt>{@code (-∞..+∞)} + * <dd>{@link #all} + * </dl> + * + * <p>Additionally, {@link Range} instances can be constructed by passing the + * {@link BoundType bound types} explicitly. + * + * <dl> + * <dt>Bounded on both ends + * <dd>{@link #range} + * <dt>Unbounded on top ({@code (a..+∞)} or {@code (a..+∞)}) + * <dd>{@link #downTo} + * <dt>Unbounded on bottom ({@code (-∞..b)} or {@code (-∞..b]}) + * <dd>{@link #upTo} + * </dl> + * + * <p>See the Guava User Guide article on <a href= + * "http://code.google.com/p/guava-libraries/wiki/RangesExplained"> + * {@code Range}</a>. + * + * @author Kevin Bourrillion + * @author Gregory Kick + * @since 10.0 + */ +@GwtCompatible +@Beta +public final class Ranges { + private Ranges() {} + + static <C extends Comparable<?>> Range<C> create( + Cut<C> lowerBound, Cut<C> upperBound) { + return new Range<C>(lowerBound, upperBound); + } + + /** + * Returns a range that contains all values strictly greater than {@code + * lower} and strictly less than {@code upper}. + * + * @throws IllegalArgumentException if {@code lower} is greater than <i>or + * equal to</i> {@code upper} + */ + public static <C extends Comparable<?>> Range<C> open(C lower, C upper) { + return create(Cut.aboveValue(lower), Cut.belowValue(upper)); + } + + /** + * Returns a range that contains all values greater than or equal to + * {@code lower} and less than or equal to {@code upper}. + * + * @throws IllegalArgumentException if {@code lower} is greater than {@code + * upper} + */ + public static <C extends Comparable<?>> Range<C> closed(C lower, C upper) { + return create(Cut.belowValue(lower), Cut.aboveValue(upper)); + } + + /** + * Returns a range that contains all values greater than or equal to + * {@code lower} and strictly less than {@code upper}. + * + * @throws IllegalArgumentException if {@code lower} is greater than {@code + * upper} + */ + public static <C extends Comparable<?>> Range<C> closedOpen( + C lower, C upper) { + return create(Cut.belowValue(lower), Cut.belowValue(upper)); + } + + /** + * Returns a range that contains all values strictly greater than {@code + * lower} and less than or equal to {@code upper}. + * + * @throws IllegalArgumentException if {@code lower} is greater than {@code + * upper} + */ + public static <C extends Comparable<?>> Range<C> openClosed( + C lower, C upper) { + return create(Cut.aboveValue(lower), Cut.aboveValue(upper)); + } + + /** + * Returns a range that contains any value from {@code lower} to {@code + * upper}, where each endpoint may be either inclusive (closed) or exclusive + * (open). + * + * @throws IllegalArgumentException if {@code lower} is greater than {@code + * upper} + */ + public static <C extends Comparable<?>> Range<C> range( + C lower, BoundType lowerType, C upper, BoundType upperType) { + checkNotNull(lowerType); + checkNotNull(upperType); + + Cut<C> lowerBound = (lowerType == BoundType.OPEN) + ? Cut.aboveValue(lower) + : Cut.belowValue(lower); + Cut<C> upperBound = (upperType == BoundType.OPEN) + ? Cut.belowValue(upper) + : Cut.aboveValue(upper); + return create(lowerBound, upperBound); + } + + /** + * Returns a range that contains all values strictly less than {@code + * endpoint}. + */ + public static <C extends Comparable<?>> Range<C> lessThan(C endpoint) { + return create(Cut.<C>belowAll(), Cut.belowValue(endpoint)); + } + + /** + * Returns a range that contains all values less than or equal to + * {@code endpoint}. + */ + public static <C extends Comparable<?>> Range<C> atMost(C endpoint) { + return create(Cut.<C>belowAll(), Cut.aboveValue(endpoint)); + } + + /** + * Returns a range with no lower bound up to the given endpoint, which may be + * either inclusive (closed) or exclusive (open). + */ + public static <C extends Comparable<?>> Range<C> upTo( + C endpoint, BoundType boundType) { + switch (boundType) { + case OPEN: + return lessThan(endpoint); + case CLOSED: + return atMost(endpoint); + default: + throw new AssertionError(); + } + } + + /** + * Returns a range that contains all values strictly greater than {@code + * endpoint}. + */ + public static <C extends Comparable<?>> Range<C> greaterThan(C endpoint) { + return create(Cut.aboveValue(endpoint), Cut.<C>aboveAll()); + } + + /** + * Returns a range that contains all values greater than or equal to + * {@code endpoint}. + */ + public static <C extends Comparable<?>> Range<C> atLeast(C endpoint) { + return create(Cut.belowValue(endpoint), Cut.<C>aboveAll()); + } + + /** + * Returns a range from the given endpoint, which may be either inclusive + * (closed) or exclusive (open), with no upper bound. + */ + public static <C extends Comparable<?>> Range<C> downTo( + C endpoint, BoundType boundType) { + switch (boundType) { + case OPEN: + return greaterThan(endpoint); + case CLOSED: + return atLeast(endpoint); + default: + throw new AssertionError(); + } + } + + /** Returns a range that contains every value of type {@code C}. */ + public static <C extends Comparable<?>> Range<C> all() { + return create(Cut.<C>belowAll(), Cut.<C>aboveAll()); + } + + /** + * Returns a range that {@linkplain Range#contains(Comparable) contains} only + * the given value. The returned range is {@linkplain BoundType#CLOSED closed} + * on both ends. + */ + public static <C extends Comparable<?>> Range<C> singleton(C value) { + return closed(value, value); + } + + /** + * Returns the minimal range that + * {@linkplain Range#contains(Comparable) contains} all of the given values. + * The returned range is {@linkplain BoundType#CLOSED closed} on both ends. + * + * @throws ClassCastException if the parameters are not <i>mutually + * comparable</i> + * @throws NoSuchElementException if {@code values} is empty + * @throws NullPointerException if any of {@code values} is null + */ + public static <C extends Comparable<?>> Range<C> encloseAll( + Iterable<C> values) { + checkNotNull(values); + if (values instanceof ContiguousSet) { + return ((ContiguousSet<C>) values).range(); + } + Iterator<C> valueIterator = values.iterator(); + C min = checkNotNull(valueIterator.next()); + C max = min; + while (valueIterator.hasNext()) { + C value = checkNotNull(valueIterator.next()); + min = Ordering.natural().min(min, value); + max = Ordering.natural().max(max, value); + } + return closed(min, max); + } +} |