Backend Development 12 min read

Guava Range API: Concepts, Construction, Operations, and Discrete Domains

This article explains Guava's Range class, covering its mathematical definition, how to construct open, closed, and bounded ranges, perform containment, connectivity, intersection, span, and query operations, and use DiscreteDomain for enumerating values, with extensive Java code examples throughout.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Guava Range API: Concepts, Construction, Operations, and Discrete Domains

Overview

In Guava, a Range<C> represents a convex subset of a comparable domain, meaning that for any a ≤ b ≤ c , if the range contains a and c it must also contain b . Ranges can be bounded or unbounded, open or closed.

Notation

(a..b) = {x | a < x < b}

[a..b] = {x | a ≤ x ≤ b}

[a..b) = {x | a ≤ x < b}

(a..b] = {x | a < x ≤ b}

(a..+∞) = {x | x > a}

[a..+∞) = {x | x ≥ a}

(-∞..b) = {x | x < b}

(-∞..b] = {x | x ≤ b}

(-∞..+∞) = all values

Endpoints may be equal, but a valid range must be either closed or half‑open; the empty range (a..a) is invalid, while [a..a) and (a..a] are empty yet legal.

Creating Ranges

Static factory methods on Range create instances:

(a..b)

open(C, C)

[a..b]

closed(C, C)

[a..b)

closedOpen(C, C)

(a..b]

openClosed(C, C)

(a..+∞)

greaterThan(C)

[a..+∞)

atLeast(C)

(-∞..b)

lessThan(C)

(-∞..b]

atMost(C)

(-∞..+∞)

all()

Example:

Range.closed("left", "right"); // strings between "left" and "right" inclusive

Explicit bound types can be supplied with range(C, BoundType, C, BoundType) , downTo(C, BoundType) , or upTo(C, BoundType) , where BoundType is CLOSED or OPEN .

Basic Operations

The contains(C) method tests membership, and containsAll(Iterable ) checks a collection. Ranges also implement Predicate for functional use.

Range.closed(1, 3).contains(2);

// true

Range.closed(1, 3).contains(4);

// false

Range.lessThan(5).contains(5);

// false

Query Operations

Methods to inspect endpoints:

hasLowerBound() / hasUpperBound()

lowerBoundType() / upperBoundType() (returns CLOSED or OPEN )

lowerEndpoint() / upperEndpoint()

isEmpty() (true for ranges like [a..a) )

Range.closedOpen(4, 4).isEmpty();

// true

Range.closed(3, 3).lowerEndpoint();

// 3

Relational Operations

Encloses : outer.encloses(inner) is true when the inner range never exceeds the outer’s bounds.

[3..6] encloses [4..5]

(3..6) encloses (3..6)

[3..6] does NOT enclose (3..6)

isConnected : Two ranges are connected if their union is a single continuous interval (excluding the empty‑range case).

Range.closed(3,5).isConnected(Range.open(5,10));

// true

Range.open(3,5).isConnected(Range.open(5,10));

// false

intersection : Returns the maximal range contained in both operands; throws IllegalArgumentException if the ranges are not connected.

Range.closed(3,5).intersection(Range.open(5,10));

// (5,5]

Range.closed(0,9).intersection(Range.closed(3,4));

// [3,4]

span : Returns the smallest range that encloses both arguments; it is the union when the ranges are connected.

Range.closed(3,5).span(Range.open(5,10));

// [3,10)

Range.open(3,5).span(Range.open(5,10));

// (3,10)

Discrete Domains

For types with a finite, enumerable set of values (e.g., Integer , Long ), Guava provides DiscreteDomain<C> . It enables operations such as ContiguousSet.create(range, domain) , which yields an immutable view of all values in the range.

ImmutableSortedSet set = ContiguousSet.create(Range.open(1,5), DiscreteDomain.integers());

// set contains [2,3,4]

Infinite domains (e.g., BigInteger ) are allowed, but ContiguousSet.create cannot be used with an infinite range because the resulting set would be unbounded.

Custom Discrete Domains

You may implement your own DiscreteDomain , but it must represent the entire value space of the type; it cannot model a partial subset such as “prime numbers” or “strings of length 5”.

Comparator Considerations

Guava’s Range requires the element type to implement Comparable , which covers most use‑cases. If a custom ordering is needed, you can either use the generic Predicate interface (e.g., Predicates.compose(range, function) ) or wrap the elements in a class that defines the desired ordering.

Source: Translated from the original Chinese tutorial (© Concurrent Programming Network)

backendJavaGuavaAPIrangeDiscreteDomain
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.