Java
Programming
Pairs
2-tuples
Data Structures

Using Pairs or 2-tuples in Java

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Java does not have a built-in tuple type in the core language, so representing a pair of values is a design choice rather than a default feature. Sometimes a generic pair is good enough, but in many cases a small named type is clearer and easier to maintain.

Use a Named Record When the Pair Has Meaning

In modern Java, the cleanest way to return or store two related values is often a record. It gives the pair names, generated accessors, and value semantics without much boilerplate.

java
1public record Coordinates(int x, int y) {}
2
3public class Demo {
4    public static Coordinates origin() {
5        return new Coordinates(0, 0);
6    }
7
8    public static void main(String[] args) {
9        Coordinates point = origin();
10        System.out.println(point.x());
11        System.out.println(point.y());
12    }
13}

If the two values mean something specific, names such as x and y are usually better than generic labels like left and right.

Use a Generic Pair Only for Truly Generic Data

Sometimes you really do need a generic two-value holder, especially in utility code or temporary transformations. In that case, a tiny pair class or record works well.

java
1public record Pair<L, R>(L left, R right) {}
2
3Pair<String, Integer> item = new Pair<>("apple", 3);
4System.out.println(item.left());
5System.out.println(item.right());

This is fine when the code is local and the semantics are obvious from context. It becomes weaker when generic pair objects start crossing larger API boundaries.

Library Options Exist, but Use Them Deliberately

If your project already uses a library that ships a pair type, reuse it instead of inventing another one. Common examples include Apache Commons and JavaFX in environments where those libraries are already present.

The main question is not "can I use a pair library?" but "does this improve the API or make it less expressive?" Pulling in a dependency purely for a generic tuple type is often unnecessary if a record would say more with less confusion.

Returning Two Values from a Method

One common reason to reach for a pair is returning two values. That is valid, but the quality of the API depends on whether the caller can tell what each slot means.

java
1public record ParseResult(boolean success, String message) {}
2
3public class Parser {
4    public ParseResult parse(String input) {
5        if (input.isBlank()) {
6            return new ParseResult(false, "input is blank");
7        }
8        return new ParseResult(true, "parsed");
9    }
10}

That is usually better than Pair<Boolean, String> because the method result becomes self-documenting.

Pairs in Collections and Stream Pipelines

Pairs are sometimes useful in intermediate processing, especially when combining two values in a stream pipeline.

java
1import java.util.List;
2
3public class StreamPairs {
4    public static void main(String[] args) {
5        List<String> names = List.of("Ada", "Linus", "Grace");
6
7        List<Pair<String, Integer>> results = names.stream()
8            .map(name -> new Pair<>(name, name.length()))
9            .toList();
10
11        System.out.println(results);
12    }
13}

This is acceptable for local transformations. If the pair escapes that narrow scope, converting it to a named type is often a better long-term decision.

Prefer Meaning Over Tuple Cleverness

Some languages encourage tuple-heavy style. Java generally reads better when domain intent is explicit. That is why records and small classes are often the most idiomatic answer even when the technical problem sounds like "I just need a 2-tuple."

Use a generic pair when it reduces ceremony in a small, obvious context. Use a named type when the values have business meaning or the API will be read by other people later.

Common Pitfalls

  • Using Pair<L, R> in public APIs where a named type would explain intent much better.
  • Adding a new tuple library just to avoid writing one small record.
  • Reusing generic pairs across unrelated domains and making code harder to read.
  • Treating pairs as a substitute for proper modeling when the data has clear semantics.
  • Returning a pair from a method without making it obvious what the two positions represent.

Summary

  • Java has no native core-language tuple type, so you choose the representation.
  • Records are usually the best option when the two values have names and meaning.
  • Generic pairs are fine for local utility code and temporary transformations.
  • Be cautious about exposing generic tuples in long-lived public APIs.
  • In Java, explicit domain names usually beat tuple-style brevity.

Course illustration
Course illustration

All Rights Reserved.