Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Groovy tuples are immutable, list-like objects for grouping a fixed number of values, including values of different types. Construct one with Tuple.tuple(...), read its values by index or v1-style property, and use multiple assignment to destructure it.

What is a Groovy tuple?

groovy.lang.Tuple represents a list of objects, but its values cannot be changed after construction. A tuple can hold heterogeneous values—for example, an integer and a string—and is useful when you want to group a fixed set of values without creating a separate class.

Groovy provides tuple classes from Tuple0 through Tuple16. That means the built-in tuple family supports up to 16 elements. The current Apache Groovy Tuple API describes Tuple as an AbstractList implementing collection and list-related interfaces, including List, Iterable, and RandomAccess.

How to create a tuple

Use the factory for concise construction

Tuple.tuple(...) chooses the tuple class based on the number of values. For example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
def tuple3 = Tuple.tuple("Groovy", "is", "great")
assert tuple3 instanceof Tuple3

Calling Tuple.tuple() with no arguments creates a Tuple0. The API documents factory overloads through Tuple16.

Use a concrete constructor when arity is explicit

You can also instantiate a specific tuple class directly:

def tuple2 = new Tuple2("Groovy", "Goodness")

This makes the arity visible in the class name. Examples in Hubert Klein Ikkink’s Groovy Goodness tutorial use Groovy 4.0.11; check syntax against the Groovy version used by your project. The current API documentation is for Groovy 5.1.0.

How to access tuple values

Tuple indices are zero-based, while the named properties begin at v1. Given this tuple:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
def mixed = Tuple.tuple(30, "minutes")

you can read its elements in several ways:

assert mixed[0] == 30
assert mixed.get(1) == "minutes"
assert mixed.v1 == 30
assert mixed.getV2() == "minutes"

def (int minutes, String period) = mixed

The final line uses multiple assignment to destructure the tuple into local variables. The declared variable types in this example correspond to the values in the tuple. Tuple methods such as size() and toArray() are also available; converting to an array preserves the values and their runtime types.

How tuples work with collection methods and slices

Since tuples behave as Lists, you can use collection operations such as findAll and collect. These operations return ordinary collection results rather than changing the immutable tuple:

def words = Tuple.tuple("Groovy", "rocks", "as", "always")

assert words.findAll { e -> e.startsWith("a") } == ["as", "always"]
assert words.collect { e -> e.toUpperCase() } ==
       ["GROOVY", "ROCKS", "AS", "ALWAYS"]

For a portion of a tuple, choose between subList and subTuple:

assert words.subList(0, 2) == ["Groovy", "rocks"]
assert words.subTuple(0, 2) == Tuple.tuple("Groovy", "rocks")

The ending index is exclusive: subList(0, 2) and subTuple(0, 2) include indices 0 and 1, not 2. subList returns a List; subTuple returns a Tuple.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How records relate to tuples

Groovy records can expose their components as a typed tuple using components(). For example:

import groovy.transform.*

@RecordOptions(components=true)
record Point(int x, int y, String color) { }

def p = new Point(100, 200, 'green')
def (int x1, int y1, String c1) = p.components()
assert p.components() instanceof Tuple3

Here, components() returns a Tuple3, which can then be destructured. This is useful when positional access or multiple assignment is convenient, while the record itself still gives its data named components such as x, y, and color. The Groovy language documentation notes that records with more components than the available TupleN classes cannot be represented by this tuple mechanism.

When to choose a tuple, list, map, or record

Type Access Mutability and shape Best fit
Tuple Positional: index, get(), or v1-style properties; supports destructuring Immutable; built-in arities from 0 to 16; values may have different types A fixed group of values where positional access is clear
List Positional, with ordinary collection operations Usually mutable; size can vary; can hold different types An ordered collection that may be added to, removed from, or processed as a collection
Map By key Usually mutable; entries are identified by keys rather than fixed positions Values that need meaningful names or key-based lookup
Record By named component Fixed set of declared components Domain data whose fields should be self-describing rather than position-dependent

Prefer a record when the values represent a domain concept and consumers benefit from named components. A tuple is a better fit when the group is small, fixed, and naturally handled by position or destructuring. Use a List for a general ordered collection and a Map when lookup by meaningful keys matters.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.