Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2008 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 java.util.Set;
 
 import  javax.annotation.Nullable;

A range (or "interval") defines the boundaries around a contiguous span of values of some Comparable type; for example, "integers from 1 to 100 inclusive." Note that it is not possible to iterate over these contained values. To do so, pass this range instance and an appropriate DiscreteDomain to ContiguousSet.create.

Types of ranges

Each end of the range may be bounded or unbounded. If bounded, there is an associated endpoint value, and the range is considered to be either open (does not include the endpoint) or closed (includes the endpoint) on that side. With three possibilities on each side, this yields nine basic types of ranges, enumerated below. (Notation: a square bracket ([ ]) indicates that the range is closed on that side; a parenthesis (( )) means it is either open or unbounded. The construct {x | statement} is read "the set of all x such that statement.")

Notation Definition Factory method
(a..b) {x | a < x < b} open
[a..b] {x | a <= x <= b}closed
(a..b] {x | a < x <= b} openClosed
[a..b) {x | a <= x < b} closedOpen
(a..+∞) {x | x > a} greaterThan
[a..+∞) {x | x >= a} atLeast
(-∞..b) {x | x < b} lessThan
(-∞..b] {x | x <= b} atMost
(-∞..+∞){x} all

When both endpoints exist, the upper endpoint may not be less than the lower. The endpoints may be equal only if at least one of the bounds is closed:

  • [a..a] : a singleton range
  • [a..a); (a..a] : empty ranges; also valid
  • (a..a) : invalid; an exception will be thrown

Warnings

  • Use immutable value types only, if at all possible. If you must use a mutable type, do not allow the endpoint instances to mutate after the range is created!
  • Your value type's comparison method should be consistent with equals if at all possible. Otherwise, be aware that concepts used throughout this documentation such as "equal", "same", "unique" and so on actually refer to whether compareTo returns zero, not whether equals returns true.
  • A class which implements Comparable<UnrelatedType> is very broken, and will cause undefined horrible things to happen in Range. For now, the Range API does not prevent its use, because this would also rule out all ungenerified (pre-JDK1.5) data types. This may change in the future.

Other notes

  • Instances of this type are obtained using the static factory methods in this class.
  • Ranges are convex: whenever two values are contained, all values in between them must also be contained. More formally, for any c1 <= c2 <= c3 of type C, r.contains(c1) && r.contains(c3) implies r.contains(c2)). This means that a Range<Integer> can never be used to represent, say, "all prime numbers from 1 to 100."
  • When evaluated as a Predicate, a range yields the same result as invoking .contains.
  • Terminology note: a range a is said to be the maximal range having property P if, for all ranges b also having property P, a.encloses(b). Likewise, a is minimal when b.encloses(a) for all b having property P. See, for example, the definition of intersection.

Further reading

See the Guava User Guide article on Range.

Author(s):
Kevin Bourrillion
Gregory Kick
Since:
10.0
@SuppressWarnings("rawtypes")
public final class Range<C extends Comparableimplements Predicate<C>, Serializable {
  private static final Function<RangeCutLOWER_BOUND_FN = new Function<RangeCut>() {
    @Override
    public Cut apply(Range range) {
      return range.lowerBound;
    }
  };
  @SuppressWarnings("unchecked")
  static <C extends Comparable<?>> Function<Range<C>, Cut<C>> lowerBoundFn() {
    return (Function;
  }
  private static final Function<RangeCutUPPER_BOUND_FN = new Function<RangeCut>() {
    @Override
    public Cut apply(Range range) {
      return range.upperBound;
    }
  };
  @SuppressWarnings("unchecked")
  static <C extends Comparable<?>> Function<Range<C>, Cut<C>> upperBoundFn() {
    return (Function;
  }
  static final Ordering<Range<?>> RANGE_LEX_ORDERING = new Ordering<Range<?>>() {
    @Override
    public int compare(Range<?> leftRange<?> right) {
      return ComparisonChain.start()
          .compare(left.lowerBoundright.lowerBound)
          .compare(left.upperBoundright.upperBound)
          .result();
    }
  };
  static <C extends Comparable<?>> Range<C> create(
      Cut<C> lowerBoundCut<C> upperBound) {
    return new Range<C>(lowerBoundupperBound);
  }

  
Returns a range that contains all values strictly greater than lower and strictly less than upper.

Throws:
IllegalArgumentException if lower is greater than or equal to upper
Since:
14.0
  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 lower and less than or equal to upper.

Throws:
IllegalArgumentException if lower is greater than upper
Since:
14.0
  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 lower and strictly less than upper.

Throws:
IllegalArgumentException if lower is greater than upper
Since:
14.0
  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 lower and less than or equal to upper.

Throws:
IllegalArgumentException if lower is greater than upper
Since:
14.0
  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 lower to upper, where each endpoint may be either inclusive (closed) or exclusive (open).

Throws:
IllegalArgumentException if lower is greater than upper
Since:
14.0
  public static <C extends Comparable<?>> Range<C> range(
      C lowerBoundType lowerType, C upperBoundType upperType) {
    checkNotNull(lowerType);
    checkNotNull(upperType);
    Cut<C> lowerBound = (lowerType == .)
        ? Cut.aboveValue(lower)
        : Cut.belowValue(lower);
    Cut<C> upperBound = (upperType == .)
        ? Cut.belowValue(upper)
        : Cut.aboveValue(upper);
    return create(lowerBoundupperBound);
  }

  
Returns a range that contains all values strictly less than endpoint.

Since:
14.0
  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 endpoint.

Since:
14.0
  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).

Since:
14.0
  public static <C extends Comparable<?>> Range<C> upTo(
      C endpointBoundType boundType) {
    switch (boundType) {
      case :
        return lessThan(endpoint);
      case :
        return atMost(endpoint);
      default:
        throw new AssertionError();
    }
  }

  
Returns a range that contains all values strictly greater than endpoint.

Since:
14.0
  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 endpoint.

Since:
14.0
  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.

Since:
14.0
  public static <C extends Comparable<?>> Range<C> downTo(
      C endpointBoundType boundType) {
    switch (boundType) {
      case :
        return greaterThan(endpoint);
      case :
        return atLeast(endpoint);
      default:
        throw new AssertionError();
    }
  }
  private static final Range<ComparableALL =
      new Range<Comparable>(Cut.belowAll(), Cut.aboveAll());

  
Returns a range that contains every value of type C.

Since:
14.0
  @SuppressWarnings("unchecked")
  public static <C extends Comparable<?>> Range<C> all() {
    return (Range;
  }

  
Returns a range that contains only the given value. The returned range is closed on both ends.

Since:
14.0
  public static <C extends Comparable<?>> Range<C> singleton(C value) {
    return closed(valuevalue);
  }

   
Returns the minimal range that contains all of the given values. The returned range is closed on both ends.

Throws:
ClassCastException if the parameters are not mutually comparable
NoSuchElementException if values is empty
NullPointerException if any of values is null
Since:
14.0
  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(minvalue);
      max = Ordering.natural().max(maxvalue);
    }
    return closed(minmax);
  }
  final Cut<C> lowerBound;
  final Cut<C> upperBound;
  private Range(Cut<C> lowerBoundCut<C> upperBound) {
    if (lowerBound.compareTo(upperBound) > 0 || lowerBound == Cut.<C>aboveAll()
        || upperBound == Cut.<C>belowAll()) {
      throw new IllegalArgumentException("Invalid range: " + toString(lowerBoundupperBound));
    }
    this. = checkNotNull(lowerBound);
    this. = checkNotNull(upperBound);
  }

  
Returns true if this range has a lower endpoint.
  public boolean hasLowerBound() {
    return  != Cut.belowAll();
  }

  
Returns the lower endpoint of this range.

Throws:
IllegalStateException if this range is unbounded below (that is, .hasLowerBound() returns false)
  public C lowerEndpoint() {
    return .endpoint();
  }

  
Returns the type of this range's lower bound: BoundType.CLOSED if the range includes its lower endpoint, BoundType.OPEN if it does not.

Throws:
IllegalStateException if this range is unbounded below (that is, .hasLowerBound() returns false)
  public BoundType lowerBoundType() {
    return .typeAsLowerBound();
  }

  
Returns true if this range has an upper endpoint.
  public boolean hasUpperBound() {
    return  != Cut.aboveAll();
  }

  
Returns the upper endpoint of this range.

Throws:
IllegalStateException if this range is unbounded above (that is, .hasUpperBound() returns false)
  public C upperEndpoint() {
    return .endpoint();
  }

  
Returns the type of this range's upper bound: BoundType.CLOSED if the range includes its upper endpoint, BoundType.OPEN if it does not.

Throws:
IllegalStateException if this range is unbounded above (that is, .hasUpperBound() returns false)
  public BoundType upperBoundType() {
    return .typeAsUpperBound();
  }

  
Returns true if this range is of the form [v..v) or (v..v]. (This does not encompass ranges of the form (v..v), because such ranges are invalid and can't be constructed at all.)

Note that certain discrete ranges such as the integer range (3..4) are not considered empty, even though they contain no actual values. In these cases, it may be helpful to preprocess ranges with canonical(DiscreteDomain).

  public boolean isEmpty() {
    return .equals();
  }

  
Returns true if value is within the bounds of this range. For example, on the range [0..2), contains(1) returns true, while contains(2) returns false.
  public boolean contains(C value) {
    checkNotNull(value);
    // let this throw CCE if there is some trickery going on
    return .isLessThan(value) && !.isLessThan(value);
  }

  
Equivalent to contains; provided only to satisfy the Predicate interface. When using a reference of type Range, always invoke contains directly instead.
  @Override public boolean apply(C input) {
    return contains(input);
  }

  
Returns true if every element in values is contained in this range.
  public boolean containsAll(Iterable<? extends C> values) {
    if (Iterables.isEmpty(values)) {
      return true;
    }
    // this optimizes testing equality of two range-backed sets
    if (values instanceof SortedSet) {
      SortedSet<? extends C> set = cast(values);
      Comparator<?> comparator = set.comparator();
      if (Ordering.natural().equals(comparator) || comparator == null) {
        return contains(set.first()) && contains(set.last());
      }
    }
    for (C value : values) {
      if (!contains(value)) {
        return false;
      }
    }
    return true;
  }

  
Returns true if the bounds of other do not extend outside the bounds of this range. Examples:
  • [3..6] encloses [4..5]
  • (3..6) encloses (3..6)
  • [3..6] encloses [4..4) (even though the latter is empty)
  • (3..6] does not enclose [3..6]
  • [4..5] does not enclose (3..6) (even though it contains every value contained by the latter range)
  • [3..6] does not enclose (1..1] (even though it contains every value contained by the latter range)

Note that if a.encloses(b), then b.contains(v) implies a.contains(v), but as the last two examples illustrate, the converse is not always true.

Being reflexive, antisymmetric and transitive, the encloses relation defines a partial order over ranges. There exists a unique maximal range according to this relation, and also numerous minimal ranges. Enclosure also implies connectedness.

  public boolean encloses(Range<C> other) {
    return .compareTo(other.lowerBound) <= 0
        && .compareTo(other.upperBound) >= 0;
  }

  
Returns true if there exists a (possibly empty) range which is enclosed by both this range and other.

For example,

  • [2, 4) and [5, 7) are not connected
  • [2, 4) and [3, 5) are connected, because both enclose [3, 4)
  • [2, 4) and [4, 6) are connected, because both enclose the empty range [4, 4)

Note that this range and other have a well-defined union and intersection (as a single, possibly-empty range) if and only if this method returns true.

The connectedness relation is both reflexive and symmetric, but does not form an Equivalence equivalence relation as it is not transitive.

Note that certain discrete ranges are not considered connected, even though there are no elements "between them." For example, [3, 5] is not considered connected to [6, 10]. In these cases, it may be desirable for both input ranges to be preprocessed with canonical(DiscreteDomain) before testing for connectedness.

  public boolean isConnected(Range<C> other) {
    return .compareTo(other.upperBound) <= 0
        && other.lowerBound.compareTo() <= 0;
  }

  
Returns the maximal range enclosed by both this range and connectedRange, if such a range exists.

For example, the intersection of [1..5] and (3..7) is (3..5]. The resulting range may be empty; for example, [1..5) intersected with [5..7) yields the empty range [5..5).

The intersection exists if and only if the two ranges are connected.

The intersection operation is commutative, associative and idempotent, and its identity element is Range.all).

Throws:
IllegalArgumentException if isConnected(connectedRange) is false
  public Range<C> intersection(Range<C> connectedRange) {
    int lowerCmp = .compareTo(connectedRange.lowerBound);
    int upperCmp = .compareTo(connectedRange.upperBound);
    if (lowerCmp >= 0 && upperCmp <= 0) {
      return this;
    } else if (lowerCmp <= 0 && upperCmp >= 0) {
      return connectedRange;
    } else {
      Cut<C> newLower = (lowerCmp >= 0) ?  : connectedRange.lowerBound;
      Cut<C> newUpper = (upperCmp <= 0) ?  : connectedRange.upperBound;
      return create(newLowernewUpper);
    }
  }

  
Returns the minimal range that encloses both this range and other. For example, the span of [1..3] and (5..7) is [1..7).

If the input ranges are connected, the returned range can also be called their union. If they are not, note that the span might contain values that are not contained in either input range.

Like intersection, this operation is commutative, associative and idempotent. Unlike it, it is always well-defined for any two input ranges.

  public Range<C> span(Range<C> other) {
    int lowerCmp = .compareTo(other.lowerBound);
    int upperCmp = .compareTo(other.upperBound);
    if (lowerCmp <= 0 && upperCmp >= 0) {
      return this;
    } else if (lowerCmp >= 0 && upperCmp <= 0) {
      return other;
    } else {
      Cut<C> newLower = (lowerCmp <= 0) ?  : other.lowerBound;
      Cut<C> newUpper = (upperCmp >= 0) ?  : other.upperBound;
      return create(newLowernewUpper);
    }
  }

  
Returns an ContiguousSet containing the same values in the given domain contained by this range.

Note: a.asSet(d).equals(b.asSet(d)) does not imply a.equals(b)! For example, a and b could be [2..4] and (1..5), or the empty ranges [3..3) and [4..4).

Warning: Be extremely careful what you do with the asSet view of a large range (such as Range.greaterThan(0)). Certain operations on such a set can be performed efficiently, but others (such as Set.hashCode or Collections.frequency) can cause major performance problems.

The returned set's Object.toString method returns a short-hand form of the set's contents, such as "[1..100]"}.

Deprecated:
Use ContiguousSet.create(range, domain). To be removed in Guava 16.0.
Throws:
IllegalArgumentException if neither this range nor the domain has a lower bound, or if neither has an upper bound
  @Beta
  @GwtCompatible(serializable = false)
  public ContiguousSet<C> asSet(DiscreteDomain<C> domain) {
    return ContiguousSet.create(thisdomain);
  }

  
Returns the canonical form of this range in the given domain. The canonical form has the following properties:
  • equivalence: a.canonical().contains(v) == a.contains(v) for all v (in other words, ContiguousSet.create(a.canonical(domain), domain).equals( ContiguousSet.create(a, domain))
  • uniqueness: unless a.isEmpty(), ContiguousSet.create(a, domain).equals(ContiguousSet.create(b, domain)) implies a.canonical(domain).equals(b.canonical(domain))
  • idempotence: a.canonical(domain).canonical(domain).equals(a.canonical(domain))

Furthermore, this method guarantees that the range returned will be one of the following canonical forms:

  • [start..end)
  • [start..+∞)
  • (-∞..end) (only if type C is unbounded below)
  • (-∞..+∞) (only if type C is unbounded below)
  public Range<C> canonical(DiscreteDomain<C> domain) {
    checkNotNull(domain);
    Cut<C> lower = .canonical(domain);
    Cut<C> upper = .canonical(domain);
    return (lower ==  && upper == ) ? this : create(lowerupper);
  }

  
Returns true if object is a range having the same endpoints and bound types as this range. Note that discrete ranges such as (1..4) and [2..3] are not equal to one another, despite the fact that they each contain precisely the same set of values. Similarly, empty ranges are not equal unless they have exactly the same representation, so [3..3), (3..3], (4..4] are all unequal.
  @Override public boolean equals(@Nullable Object object) {
    if (object instanceof Range) {
      Range<?> other = (Range<?>) object;
      return .equals(other.lowerBound)
          && .equals(other.upperBound);
    }
    return false;
  }

  
Returns a hash code for this range.
  @Override public int hashCode() {
    return .hashCode() * 31 + .hashCode();
  }

  
Returns a string representation of this range, such as "[3..5)" (other examples are listed in the class documentation).
  @Override public String toString() {
    return toString();
  }
  private static String toString(Cut<?> lowerBoundCut<?> upperBound) {
    StringBuilder sb = new StringBuilder(16);
    lowerBound.describeAsLowerBound(sb);
    sb.append('\u2025');
    upperBound.describeAsUpperBound(sb);
    return sb.toString();
  }

  
Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557
  private static <T> SortedSet<T> cast(Iterable<T> iterable) {
    return (SortedSet<T>) iterable;
  }
    if (this.equals()) {
      return all();
    } else {
      return this;
    }
  }
  @SuppressWarnings("unchecked"// this method may throw CCE
  static int compareOrThrow(Comparable leftComparable right) {
    return left.compareTo(right);
  }
  private static final long serialVersionUID = 0;
New to GrepCode? Check out our FAQ X