# How to Use Guava's Range Class for Interval Operations in Java

> Master Guava's Range class for efficient Java interval operations. Learn to define, test, and combine intervals with clear examples.

- Repository: [Google/guava](https://github.com/google/guava)
- Tags: how-to-guide
- Published: 2026-08-10

---

**Guava's immutable `Range<C>` class represents intervals of comparable values using two bounds—lower and upper—that can be open, closed, or unbounded, providing methods for membership testing, intersection, and spanning.**

The `Range` class in Google's Guava library (google/guava) provides a robust, immutable implementation of mathematical intervals for Java applications. Unlike standard Java collections, Guava Range handles continuous or discrete value ranges with precise boundary semantics, making it ideal for validating inputs, querying date ranges, or implementing scheduling logic. The class is implemented in [`guava/src/com/google/common/collect/Range.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/collect/Range.java) and is built atop the internal `Cut<C>` abstraction.

## Creating Ranges with Static Factory Methods

The public API of `Range` consists of static factory methods that create the nine basic range types by assembling appropriate `Cut` instances. These methods are located in [`guava/src/com/google/common/collect/Range.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/collect/Range.java) between lines 45 and 82.

### Basic Range Types

You can construct ranges using intuitive factory methods that specify whether each bound is inclusive (closed) or exclusive (open):

- **`Range.open(lower, upper)`**: Creates an exclusive range `(lower..upper)` using `Cut.aboveValue(lower)` and `Cut.belowValue(upper)`.
- **`Range.closed(lower, upper)`**: Creates an inclusive range `[lower..upper]`.
- **`Range.closedOpen(lower, upper)`**: Creates `[lower..upper)`.
- **`Range.openClosed(lower, upper)`**: Creates `(lower..upper]`.
- **`Range.singleton(value)`**: Creates a closed range containing exactly one value.
- **`Range.all()`**: Creates an unbounded range `(-∞..+∞)`.

```java
Range<Integer> open = Range.open(1, 5);          // (1..5)
Range<Integer> closed = Range.closed(1, 5);      // [1..5]
Range<Integer> closedOpen = Range.closedOpen(1, 5); // [1..5)
Range<Integer> all = Range.all();               // (-∞..+∞)

```

### Custom Bounds with BoundType

For dynamic bound configuration, use the generic `range(lower, lowerType, upper, upperType)` factory with the `BoundType` enum defined in [`guava/src/com/google/common/collect/BoundType.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/collect/BoundType.java). This enum specifies whether each endpoint is `OPEN` or `CLOSED`:

```java
Range<Integer> custom = Range.range(1, BoundType.CLOSED, 10, BoundType.OPEN); // [1..10)

```

## The Cut Abstraction and Internal Architecture

In [`guava/src/com/google/common/collect/Range.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/collect/Range.java), the `Range<C>` class stores two `Cut<C>` objects: `lowerBound` and `upperBound`. The `Cut` hierarchy—defined in [`guava/src/com/google/common/collect/Cut.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/collect/Cut.java)—encodes the four possible physical states of a bound (below all, above all, below a specific value, above a specific value) and supplies the comparison logic used by all range operations.

This architecture allows `Range` to handle complex boundary semantics consistently across all operations without requiring separate `Interval` classes.

## Testing Membership and Set Operations

`Range` implements `Predicate<C>` (and Java 8's `java.util.function.Predicate<C>`), allowing it to be used wherever a predicate is required. The `contains` method at lines 103-110 in [`Range.java`](https://github.com/google/guava/blob/main/Range.java) provides the canonical membership test.

### Membership Testing

```java
boolean contains3 = closed.contains(3);          // true
boolean contains5 = closedOpen.contains(5);      // false

```

### Composite Operations

The class provides mathematical set operations defined in terms of the underlying `Cut` ordering:

- **`intersection(Range other)`** (lines 135-156): Returns the maximal range enclosed by both ranges.
- **`span(Range other)`** (lines 106-122): Returns the minimal range that encloses both ranges.
- **`encloses(Range other)`**: Returns true if the bounds of the other range do not extend outside this range's bounds.
- **`isConnected(Range other)`**: Returns true if there exists a range that encloses both ranges.

```java
Range<Integer> r1 = Range.closed(1, 4);   // [1..4]
Range<Integer> r2 = Range.closed(3, 6);   // [3..6]
Range<Integer> intersect = r1.intersection(r2); // [3..4]
Range<Integer> span = r1.span(r2);               // [1..6]
boolean encloses = r1.encloses(Range.singleton(2)); // true

```

## Enumerating Discrete Values with ContiguousSet

`Range` does **not** iterate over the values it contains. To enumerate discrete values (such as integers), combine a `Range` with a `DiscreteDomain` via `ContiguousSet.create()`:

```java
ImmutableSortedSet<Integer> ints = ContiguousSet.create(
        Range.closed(1, 5), DiscreteDomain.integers()); // {1,2,3,4,5}

```

## Summary

- **Immutable architecture**: `Range<C>` uses two `Cut<C>` objects to represent bounds, ensuring thread safety and consistent behavior across all operations.
- **Flexible construction**: Use static factories like `open()`, `closed()`, and `range()` with `BoundType` to create the nine basic interval types.
- **Predicate support**: `Range` implements `Predicate<C>`, enabling functional-style membership testing with the `contains()` method.
- **Set operations**: Perform mathematical operations including `intersection()`, `span()`, and `encloses()` with guaranteed correctness for all bound combinations.
- **Discrete enumeration**: Use `ContiguousSet.create()` with a `DiscreteDomain` to iterate over integer ranges; `Range` itself does not support iteration.
- **Validation**: Empty ranges like `[a..a)` are allowed, but invalid ranges like `(a..a)` throw `IllegalArgumentException` during construction.

## Frequently Asked Questions

### What is the difference between open and closed bounds in Guava Range?

**Open bounds** (exclusive) exclude the endpoint value, denoted by parentheses in mathematical notation `(a..b)`, while **closed bounds** (inclusive) include the endpoint, denoted by brackets `[a..b]`. In Guava, `Range.open(1, 5)` contains 2, 3, and 4 but not 1 or 5, whereas `Range.closed(1, 5)` contains all integers from 1 through 5. The `BoundType` enum in [`guava/src/com/google/common/collect/BoundType.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/collect/BoundType.java) explicitly defines these as `OPEN` and `CLOSED`.

### How do I check if two ranges overlap or connect?

Use the `isConnected()` method to determine if there exists any value (or range) that could connect two ranges, or use `intersection()` to get the overlapping portion. If ranges are not connected, `intersection()` throws an `IllegalArgumentException`. For example, `Range.closed(1, 4).isConnected(Range.closed(3, 6))` returns true because the ranges share values 3 and 4.

### Can I use Guava Range with custom comparable types?

Yes, `Range<C>` requires type parameter `C` to extend `Comparable<C>`. Any class implementing `Comparable` can be used with Range, including custom domain objects, dates, or timestamps. The underlying `Cut` abstraction in [`guava/src/com/google/common/collect/Cut.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/collect/Cut.java) handles the comparison logic using the type's natural ordering.

### Why does creating a range throw an IllegalArgumentException?

Guava validates range boundaries during construction to ensure the lower bound does not exceed the upper bound. Ranges like `(a..a)` or `(5..3)` are considered empty or invalid and throw `IllegalArgumentException`. However, certain empty ranges like `[a..a)` (closed-open with same value) are explicitly allowed as valid empty intervals.