
Java Pair – A Simple Way to Store Two Related Values
Introduction
When working with Java, developers often need to store and pass two related values as a single unit. While many programming languages provide built-in support for tuples or pairs, Java’s standard library does not have a dedicated “Pair” class. This means that developers must rely on third-party libraries or JavaFX’s “Pair” or create their own implementation if they need an easy way to store two related values.
Why do we need a pair in Java?
There are many situations where a “Pair” is useful, for example:
- Returning multiple values from one method – Java methods can only return a single value, but with a “Pair” we can return two related values.
- Store key-value mappings – While a “map” is often used for this purpose, sometimes we need a lightweight structure to store a single key-value pair without using a full-fledged map.
- Graph algorithms and coordinate systems – A “pair” is often used to represent edges in graphs (
(node1, node2)
) or points in a coordinate system ((x, y)
). - Caching and lookup tables – Sometimes we need to link two pieces of data together, for example a cache entry with a timestamp or a query with its result.
Why doesn’t Java have a built-in pair?
Unlike other languages like Python (with tuples) or Kotlin (with data classes), Java encourages developers to create well-defined classes instead of using generic structures like Pair
. While the use of pairs can be convenient, it sometimes makes code more difficult to read and maintain. For example, a “pair” doesn’t say much about the meaning of the two values, whereas a class like “EmployeeSalary(String Name, int Salary)” is much more meaningful.
In cases where we need a simple, temporary structure to store two related values, a “pair” can be a practical solution. In this blog, we’ll explore different ways to use pairs in Java, including JavaFX’s built-in pair, Apache Commons Lang’s pair, and our own implementations. We will also look at modern alternatives such as Java Records, introduced in Java 14.
What is a Java Pair?
A Pair in Java is a simple data structure that contains two related values as a single unit. It is often used when two values need to be grouped together without creating a separate class. The two values in a Pair are usually referred to as first and second elements.
Definition and concept of a Pair
A Pair is essentially a container object that contains two heterogeneous (different types) or homogeneous (same types) values. It provides methods for retrieving these values and is therefore useful in scenarios where a small, lightweight data structure is required.
For example, imagine a scenario where we need to return both the minimum value and the maximum value from an array. Instead of returning them separately, we can use a Pair to return them together:
Pair minMax = new Pair<>(10, 100);
System.out.println("Min: " + minMax.getKey());
System.out.println("Max: " + minMax.getValue());
Important properties of a Java Pair
- Stores exactly two values.
- Can contain different types of values (
Pair
orPair
). - Provides getter methods to access the values (like
getKey()
andgetValue()
inPair
of JavaFX). - Normally immutable, depending on the implementation.
- Can be used to return multiple values from a method.
- Improves readability and simplicity of code when processing two related values.
Common use cases for Pair in Java
Returning multiple values from one method
Java does not directly support multiple return values. A Pair can be used to return two related values:
import javafx.util.Pair;
public class PairExample {
public static Pair findMinMax(int[] numbers) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int num : numbers) {
if (num < min) min = num;
if (num > max) max = num;
}
return new Pair<>(min, max);
}
public static void main(String[] args) {
int[] nums = {5, 1, 9, 7, 3};
Pair result = findMinMax(nums);
System.out.println("Min: " + result.getKey() + ", Max: " + result.getValue());
}
}
Storing Key-Value Pairs
A Pair
is useful in cases where we need a simple key-value relationship without using a Map
. Example:
Pair productPrice = new Pair<>("Laptop", 75000.00);
System.out.println("Product: " + productPrice.getKey() + ", Price: " + productPrice.getValue());
Displaying a Graph Edge (Node Relationships)
When working with graphs, a Pair can represent an edge between two nodes:
Pair edge = new Pair<>("A", "B");
System.out.println("Edge connects: " + edge.getKey() + " -> " + edge.getValue());
Saving two related values in data structures
A pair is useful in collections such as lists and sets:
List> studentMarks = new ArrayList<>();
studentMarks.add(new Pair<>("Alice", 85));
studentMarks.add(new Pair<>("Bob", 92));
Caching results with a timestamp
A pair can be used in caching scenarios where we store data together with a timestamp:
Pair cacheEntry = new Pair<>("Cached Data", System.currentTimeMillis());
Using JavaFX’s Pair
class
JavaFX provides a built-in “Pair” class in the “javafx.util” package, which is one of the easiest ways to use a Pair in Java. With this class, developers can store two related values without having to create a separate class.
Introduction to javafx.util.Pair
The “Pair” class in JavaFX is a simple, generic class that represents a key-value pair. It provides methods to retrieve these values:
getKey()
– Returns the first element (key).getValue()
– Returns the second element (value).
Importing and using JavaFX’s Pair
To use Pair
, you need to import it from the JavaFX package:
import javafx.util.Pair;
Here is a simple example of using Pair
:
import javafx.util.Pair;
public class PairExample {
public static void main(String[] args) {
// Create a Pair
Pair student = new Pair<>("Alice", 85);
// Retrieve values
System.out.println("Name of the student: " + student.getKey());
System.out.println("Score: " + student.getValue());
}
}
Main features of JavaFX’s Pair
- Unchangeable values: Once created, the key and value cannot be changed.
- Easy to use: Provides a straightforward way to store two related values.
- Limited functionality: Provides only the
getKey()
andgetValue()
methods; lacks additional functions such as comparison, modification or serialization.
Example: Returning multiple values from one method
One of the most common uses of Pair
is to return multiple values from one method:
import javafx.util.Pair;
public class MinMaxFinder {
public static Pair findMinMax(int[] numbers) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int num : numbers) {
if (num < min) min = num;
if (num > max) max = num;
}
return new Pair<>(min, max);
}
public static void main(String[] args) {
int[] numbers = {3, 8, 1, 5, 9};
Pair result = findMinMax(numbers);
System.out.println("Min: " + result.getKey());
System.out.println("Max: " + result.getValue());
}
}
Example: Storing Key-Value Pairs in a list
The JavaFX class Pair
is useful if you want to save several key-value pairs in a list.
import javafx.util.Pair;
import java.util.ArrayList;
import java.util.List;
public class PairListExample {
public static void main(String[] args) {
List> products = new ArrayList<>();
// Adding key-value pairs
products.add(new Pair<>("Laptop", 75000.00));
products.add(new Pair<>("Phone", 50000.00));
products.add(new Pair<>("Tablet", 30000.00));
// Iterate through the list
for (Pair product : products) {
System.out.println("Product: " + product.getKey() + ", Price: ₹" + product.getValue());
}
}
}
Limitations of JavaFX’s Pair
Although javafx.util.Pair
is easy to use, it has some limitations:
- Invariant – There is no way to change the values after creation.
- Limited methods – It only provides
getKey()
andgetValue()
, but no additional functions like comparison or serialization. - JavaFX dependency – Requires JavaFX, which may not always be available in non-GUI projects.
- Not widely used – Java developers often prefer third-party libraries (such as Apache Commons Lang) or custom implementations.
When should you use JavaFX Pair
?
- When you need a quick and easy way to store two values.
- When working within a JavaFX project (since the library is already available).
- For simple use cases where immutability is not important.
Limitations of JavaFX Pair
While JavaFX javafx.util.Pair
provides an easy way to store two related values, it has some limitations that make it less suitable for certain use cases. In this section, we discuss the drawbacks of JavaFX Pair
and explain why developers might prefer alternative implementations.
Immutability
One of the main limitations of Pair
is that it is immutable — you cannot change its values once it has been created. This means:
- There are no setter methods to update the “key” or “value”.
- If you want to change the values, you need to create a new instance of “Pair”.
Example:
import javafx.util.Pair;
public class ImmutablePairExample {
public static void main(String[] args) {
Pair student = new Pair<>("Alice", 85);
// This will not work because Pair does not provide setter methods
// student.setKey("Bob"); // ERROR
// student.setValue(90); // ERROR
// Instead, you have to create a new Pair
student = new Pair<>("Bob", 90);
System.out.println("Updated student: " + student.getKey() + " - " + student.getValue());
}
}
Effect:
- If your application needs to be changed frequently, using “Pair” can lead to unnecessary objects being created, which increases memory consumption.
- Alternative approaches such as mutable custom classes or third-party libraries offer more flexibility.
Limited functionality
The JavaFX class “Pair” offers only two methods:
getKey()
getValue()
It lacks additional methods that could make it more useful, such as:- Comparison (
equals()
andhashCode()
are available, but not customizable). - Serialization support (e.g. to convert a “Pair” to JSON).
- Custom formatting for displaying pairs.
Example:
If you want to format a “Pair” as a readable string, you have to manually override “toString()” in a wrapper class.
import javafx.util.Pair;
public class PairToStringExample {
public static void main(String[] args) {
Pair product = new Pair<>("Laptop", 75000.00);
System.out.println("Product data: (" + product.getKey() + ", " + product.getValue() + ")");
}
}
Effects:
- You may need to write additional helper methods to work around these limitations.
- Other libraries, such as Apache Commons Lang, offer more extensive functions.
JavaFX dependency
The class javafx.util.Pair
is part of the JavaFX library, which is not included in the standard Java distributions (since Java 11). This means:
- You can only use
Pair
if JavaFX is included in your project. - If you are not working on a JavaFX application, it does not make sense to add JavaFX only for “Pair”.
Example problem
If you use Pair
in a Java project without JavaFX, you may get this error:
Error: Package javafx.util does not exist
Implications:
- Developers using non-GUI projects must find alternatives such as Apache Commons Lang or own implementations.
- Additional dependencies can unnecessarily increase the project size.
Not widely used in Java development
Since javafx.util.Pair
is part of JavaFX, it is not widely used in enterprise applications or backend systems. Most Java developers prefer third-party libraries such as Apache Commons Lang or Google Guava, which offer more feature-rich alternatives.
Alternative approaches:
- Apache Commons Lang: Provides
Pair
,ImmutablePair
andMutablePair
with extended functionality. - Google Guava: Provides
ImmutablePair
with built-in support for immutability. - Custom Pair Class: If you need a lightweight solution without dependencies.
Apache Commons Lang Pair
use
The Apache Commons Lang library provides a robust implementation of the “Pair” class that offers more flexibility compared to JavaFX’s “Pair”. It is part of the package “org.apache.commons.lang3.tuple” and includes several variants, such as “Pair”, “ImmutablePair” and “MutablePair”.
Introduction to Apache Commons Lang Pair
The Apache Commons Lang library includes:
Pair
– A generic abstract class that can be used to define pairs.ImmutablePair
– A subclass ofPair
that prevents changes.MutablePair
– A subclass ofPair
that allows values to be changed.
This implementation provides additional functions such as:- Options for mutability and immutability.
- Customizable serialization and comparison methods.
- A more intuitive API compared to JavaFX’s
Pair
.
Add Apache Commons Lang to your project
To use Apache Commons Lang’s Pair
, add the following Maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
For Gradle:
dependencies {
implementation 'org.apache.commons:commons-lang3:3.12.0'
}
Once added, you can import and use Pair
in your Java application.
Create and use a Pair
The Apache Commons class “Pair” is an abstract class, so you usually use one of its concrete implementations: ImmutablePair
or MutablePair
.
Example: Creating an immutable Pair
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
public class ImmutablePairExample {
public static void main(String[] args) {
Pair student = new ImmutablePair<>("Alice", 85);
System.out.println("Student: " + student.getLeft());
System.out.println("Score: " + student.getRight());
}
}
Here getLeft()
and getRight()
are used instead of getKey()
and getValue()
.
Example: Creating a changeable Pair
If you need to change values after creation, use MutablePair
:
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
public class MutablePairExample {
public static void main(String[] args) {
MutablePair student = new MutablePair<>("Alice", 85);
// Change the values
student.setLeft("Bob");
student.setRight(90);
System.out.println("Updated student: " + student.getLeft() + " - " + student.getRight());
}
}
Main features of Apache Commons Pair
Provides both mutable and immutable variants
ImmutablePair
ensures that values cannot be changed.- with
MutablePair
values can be changed withsetLeft()
andsetRight()
.
More intuitive naming conventions
Instead of getKey()
and getValue()
are used:
getLeft()
– Represents the first element of the pair.getRight()
– Represents the second element of the pair.
This makes it easier to distinguish between key-value pairs and general relationships.
Supports serialization
The Apache Commons Pair
implementations implement Serializable
, making them suitable for use in distributed systems and file stores.
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.io.*;
public class PairSerializationExample {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// Create an ImmutablePair
ImmutablePair student = new ImmutablePair<>("Alice", 85);
// Serialize the Pair
FileOutputStream fileOut = new FileOutputStream("pair.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(student);
out.close();
fileOut.close();
// Deserialize the Pair
FileInputStream fileIn = new FileInputStream("pair.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
ImmutablePair deserializedStudent = (ImmutablePair) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized student: " + deserializedStudent.getLeft() + " - " + deserializedStudent.getRight());
}
}
Supports equals()
and hashCode()
The Apache Commons Pair
class provides robust implementations of equals()
and hashCode()
, making it useful for comparisons and collections.
Example:
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class PairComparisonExample {
public static void main(String[] args) {
Pair pair1 = new ImmutablePair<>("Alice", 85);
Pair pair2 = new ImmutablePair<>("Alice", 85);
System.out.println("Are the pairs equal? " + pair1.equals(pair2)); // true
}
}
Use cases for Apache Commons Pair
Returning multiple values from one method
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class MinMaxExample {
public static Pair findMinMax(int[] numbers) {
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
for (int num : numbers) {
if (num < min) min = num;
if (num > max) max = num;
}
return new ImmutablePair<>(min, max);
}
public static void main(String[] args) {
int[] numbers = {3, 8, 1, 5, 9};
Pair result = findMinMax(numbers);
System.out.println("Min: " + result.getLeft() + ", Max: " + result.getRight());
}
}
Storing Key-Value Pairs in a List
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.ArrayList;
import java.util.List;
public class PairListExample {
public static void main(String[] args) {
List> products = new ArrayList<>();
products.add(new ImmutablePair<>("Laptop", 75000.00));
products.add(new ImmutablePair<>("Phone", 50000.00));
products.add(new ImmutablePair<>("Tablet", 30000.00));
for (Pair product : products) {
System.out.println("Product: " + product.getLeft() + ", Price: ₹" + product.getRight());
}
}
}
Creating a custom pair class
Although third-party libraries such as Apache Commons Lang provide a “pair” implementation, sometimes a custom pair class is a better choice. This is especially true if you:
- Don’t want external dependencies in your project.
- need additional functionality that goes beyond the standard “Pair” implementations.
- want better readability by defining meaningful variable names.
In this section, we’ll learn why and when you should create your own Pair class, followed by a step-by-step implementation.
Why create your own pair class?
Although JavaFX and Apache Commons Lang offer pre-built “pair” implementations, there are good reasons to create your own:
No external dependencies
- JavaFX’s
Pair
requires JavaFX, and Apache Commons Lang adds an external library. - Having your own
Pair
keeps your code lean.
Better readability
- Instead of using
Pair.getLeft()
andPair.getRight()
, a custom class allows for meaningful names likeEmployee.getName()
andEmployee.getSalary()
.
Customization & additional methods
- You may need additional functions such as data validation, default values or helper methods.
Performance aspects
- With a custom class, you can control memory allocation and immutability, avoiding the creation of unnecessary objects.
Implementation of a basic generic pair class
A generic “pair” class allows you to store any type of objects together.
public class Pair {
private final K key;
private final V value;
// constructor
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
// Getter
public K getKey() {
return key;
}
public V getValue() {
return value;
}
// Override toString() for better display
@Override
public String toString() {
return "(" + key + ", " + value + ")";
}
}
Example of use
public class PairTest {
public static void main(String[] args) {
Pair student = new Pair<>("Alice", 85);
System.out.println("Student: " + student.getKey() + ", Score: " + student.getValue());
}
}
This implementation provides a simple and immutable pair
. However, if we need a changeable version, we can customize it accordingly.
Create a mutable pair class
If you need to modify values after creation, a modifiable pair
can be useful.
public class MutablePair {
private K key;
private V value;
// constructor
public MutablePair(K key, V value) {
this.key = key;
this.value = value;
}
// Getter and setter
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
@Override
public String toString() {
return "(" + key + ", " + value + ")";
}
}
Example of use
public class MutablePairTest {
public static void main(String[] args) {
MutablePair student = new MutablePair<>("Alice", 85);
// Change the values
student.setKey("Bob");
student.setValue(90);
System.out.println("Updated student: " + student.getKey() + " - " + student.getValue());
}
}
Adding additional functions to Pair
A custom class “Pair” allows you to add user-defined methods, such as:
- equality checks
- Swap values
- serialization
Adding equals()
and hashCode()
To make Pair
work correctly in HashMaps, Sets and Lists, overwrite equals()
and hashCode()
.
import java.util.Objects;
public class Pair {
private final K key;
private final V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return Objects.equals(key, pair.key) && Objects.equals(value, pair.value);
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
}
Example of use
public class PairEqualityTest {
public static void main(String[] args) {
Pair p1 = new Pair<>("Alice", 85);
Pair p2 = new Pair<>("Alice", 85);
System.out.println("Are the pairs equal? " + p1.equals(p2)); // true
}
}
Adding a swap method
A swap()
method makes it possible to swap key and value.
public class Pair {
private final K key;
private final V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public Pair swap() {
return new Pair<>(value, key);
}
}
Usage example
public class PairSwapTest {
public static void main(String[] args) {
Pair p = new Pair<>("Alice", 85);
Pair swapped = p.swap();
System.out.println("Swapped Pair: " + swapped.getKey() + ", " + swapped.getValue());
}
}
When to use a user-defined Pair class
A custom “Pair” class is preferable if:
- You don’t want external dependencies (Apache Commons Lang, JavaFX).
- You need additional functions (e.g. swap, serialization).
- You want better readability with meaningful class names.
However, if you only need a simple key-value structure without additional logic, Pair from Apache Commons Langis the better choice.
Java Record as an alternative
With the introduction of Java Records in Java 14, developers now have a new and efficient way to create immutable data structures. Records are a manageable and readable alternative to Pair
, especially when working with small data structures that only contain values.
In this section we will look at:
- What Java Records are
- How they can replace “pairs“
- Advantages of using records
- Comparison with other Pair implementations
What is a Java record?
A record is a special type of Java class that contains immutable data. Unlike conventional classes, records create data:
- Automatically generate constructors, getters,
equals()
,hashCode()
andtoString()
. - Are immutable, i.e. the values cannot be changed after creation.
- Improve readability by reducing tinkering code.
Example: Traditional Java class vs. data set
Without record (standard Java class)
public class Employee {
private final String name;
private final int Salary;
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
public String getName() { return name; }
public int getSalary() { return Salary; }
@Override
public String toString() {
return "Employee{name='" + name + "', salary=" + salary + "}";
}
}
With record (Java 14+)
public record Employee(String name, int salary) { }
In just one line Java creates automatically:
- Constructor
- Getter (
Name()
,Salary()
) toString()
equals()
hashCode()
How Java Records can replace Pair
Since records are meant for immutable data, they can replace pair“ if you need to store two related values.
Example: Using a “Pair”
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class PairExample {
public static void main(String[] args) {
Pair student = new ImmutablePair<>("Alice", 85);
System.out.println("Student: " + student.getLeft() + ", Score: " + student.getRight());
}
}
Rewrite with Java Record
public record Student(String name, int score) { }
public class RecordExample {
public static void main(String[] args) {
Student Student = new Student("Alice", 85);
System.out.println("Student: " + student.name() + ", Score: " + student.score());
}
}
Advantages of using Records compared to Pair
:
- Improved readability (meaningful field names instead of
getLeft()
andgetRight()
). - No dependency on external libraries like Apache Commons Lang.
- Less boilerplate code (automatic
toString()
,equals()
andhashCode()
).
Best use cases for data sets
Java Records are ideal for:
- returning multiple values from one method
- Key-value links with meaningful names
- Immutable data storage (e.g. settings, configurations)
- Data transfer objects (DTOs) in APIs
Example: Returning multiple values from one method
Instead of using “pairs”, we can return a data set:
public record MinMax(int min, int max) { }
public class MinMaxExample {
public static MinMax findMinMax(int[] numbers) {
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
for (int num : numbers) {
if (num < min) min = num;
if (num > max) max = num;
}
return new MinMax(min, max);
}
public static void main(String[] args) {
int[] numbers = {3, 8, 1, 5, 9};
MinMax result = findMinMax(numbers);
System.out.println("Min: " + result.min() + ", Max: " + result.max());
}
}
Additional functions of Java Records
Adding your own methods
Even if records automatically generate basic methods, you can still add your own methods.
public record Product(String name, double price) {
public String formattedPrice() {
return "₹" + price;
}
}
public class RecordMethodExample {
public static void main(String[] args) {
Product product = new Product("Laptop", 75000.00);
System.out.println(product.name() + " costs " + product.formattedPrice());
}
}
Comparison: Java Records vs. Pair
Feature | Java Record | JavaFX Pair | Apache Commons Pair |
---|---|---|---|
Readability | Excellent (meaningful names) | Poor (generic key values) | Poor (generic key values) |
Boilerplate Code | Minimal | Requires Getter | Requires Getter |
Variability | Immutable | Immutable | Mutable (MutablePair) |
External dependency | No | Requires JavaFX | Requires Apache Commons Lang |
Serialization | Yes (implements Serializable ) | No | Yes |
Best use cases | DTOs, immutable data structures, multiple returns | Small key-value pairs in JavaFX applications | General use cases |
When should you use Java Records instead of Pair
?
Use Java Records when:
You need immutable data storage.
You want better readability with meaningful field names.
You want to return several values from one method.
You want to avoid dependencies on external libraries.
Use Apache Commons Pair
if:
You need modifiable pairs (MutablePair
).
You are working with older Java versions (before Java 14).
You need a lightweight solution for the temporary storage of key values.
Best practices for the use of pairs in Java
While using pairs can be convenient, it is important to follow best practices to ensure code readability, maintainability and efficiency.
In this section, we will look at:
- When to use a Pair
- When to avoid a Pair
- readability and maintainability considerations
- Performance considerations
- Alternatives to Pair
When is a Pair used?
The use of a Pair is appropriate in the following situations:
Returning multiple values from one method
- When a method must return two related values.
- Example: A method that returns both the minimum and maximum value of an array.
Temporary storage of key values - If you need to link two values temporarily without creating a separate class.
- Example: Caching a result with its timestamp.
Graphical data structures - Represents an edge between two nodes.
- Example:
(node1, node2)
in a graph algorithm.
Storing structured data in collections - When using lists or sets to store two-part data.
- Example: A list of student names and grades.
Example: Using Pair
to return multiple values
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class MinMaxFinder {
public static Pair findMinMax(int[] numbers) {
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
for (int num : numbers) {
if (num < min) min = num;
if (num > max) max = num;
}
return new ImmutablePair<>(min, max);
}
public static void main(String[] args) {
int[] numbers = {3, 8, 1, 5, 9};
Pair result = findMinMax(numbers);
System.out.println("Min: " + result.getLeft() + ", Max: " + result.getRight());
}
}
When to avoid using a Pair
Using a Pair is not always the best option. In some cases it can affect the readability of the code.
When field names are important
- If the meaning of
Pair.getLeft()
andPair.getRight()
is unclear, use a separate class instead. - Better alternative: Use a meaningful class like “StudentNote”.
If the data structure is complex - If you need more than two values, consider using a class instead.
When performance is critical - Creating a new instance of “Pair” each time can lead to unnecessary object creation.
- Use primitive types or arrays when possible.
Readability and maintainability considerations
Use a named class instead of a generic Pair
Using a named class improves the clarity of the code.
Bad example: Unnecessary use of a Pair
Pair student = new ImmutablePair<>("Alice", 85);
System.out.println("Student: " + student.getLeft() + ", Score: " + student.getRight());
Better example: Using a separate class
public record StudentScore(String name, int score) { }
public class RecordExample {
public static void main(String[] args) {
StudentScore student = new StudentScore("Alice", 85);
System.out.println("Student: " + student.name() + ", Score: " + student.score());
}
}
Advantage: The field names name()
and score()
improve clarity.
Performance considerations
The use of pairs can lead to unnecessary object creation. Consider alternatives for better performance.
Use an array instead of a Pair
If both values are of the same type, an array may be more efficient.
public class ArrayExample {
public static int[] findMinMax(int[] numbers) {
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
for (int num : numbers) {
if (num < min) min = num;
if (num > max) max = num;
}
return new int[]{min, max};
}
public static void main(String[] args) {
int[] result = findMinMax(new int[]{3, 8, 1, 5, 9});
System.out.println("Min: " + result [0] + ", Max: " + result [1]);
}
}
Advantage: Reduces object creation and memory consumption.
Alternatives to Pair
Alternative | When to use |
---|---|
Java Record | If you need immutable structured data with meaningful names. |
Custom Class | When data needs additional functionality. |
Apache Commons Pair | When you need a fast, generic two-value structure. |
Tuple (from a library like Vavr) | When you want to store multiple values in a functional style. |
Array | If both elements are of the same type and performance matters. |
Example: Using Vavr’s Tuple instead of Pair
Vavr is a functional programming library that offers Tuple as an alternative.
import io.vavr.Tuple;
import io.vavr.Tuple2;
public class VavrTupleExample {
public static void main(String[] args) {
Tuple2 student = Tuple.of("Alice", 85);
System.out.println("Student: " + student._1 + ", Score: " + student._2);
}
}
Advantage: Supports tuples with more than two values.
Use cases and practical examples for Pair object in Java
A “Pair” is useful in various programming scenarios where two related values need to be stored together. In this section, we will look at real use cases of “Pair” and how it can be used in practical applications.
General use cases
Some of the most common use cases of “Pair” in Java are:
- returning multiple values from a method
- Key-value associations in data structures
- Graph algorithms (edges and relationships)
- Mapping of database query results
- Saving coordinates in 2D/3D space
- Saving results temporarily with timestamps
- Display HTTP headers
- Linking metadata to data in logging systems
Return multiple values from one method
Since Java does not support the direct return of multiple values, a Pair
can be used to efficiently return two related values.
Example: Finding minimum and maximum values in an array
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class MinMaxFinder {
public static Pair findMinMax(int[] numbers) {
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
for (int num : numbers) {
if (num < min) min = num;
if (num > max) max = num;
}
return new ImmutablePair<>(min, max);
}
public static void main(String[] args) {
int[] numbers = {3, 8, 1, 5, 9};
Pair result = findMinMax(numbers);
System.out.println("Min: " + result.getLeft() + ", Max: " + result.getRight());
}
}
Why use a Pair? It allows two related values to be returned without creating a separate class.
Storing key-value associations in data structures
Pairs are useful for storing key-value associations in lists without the need for a full Map.
Example: Saving Student names and grades
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.ArrayList;
import java.util.List;
public class StudentScores {
public static void main(String[] args) {
List> studentScores = new ArrayList<>();
studentScores.add(new ImmutablePair<>("Alice", 85));
studentScores.add(new ImmutablePair<>("Bob", 90));
studentScores.add(new ImmutablePair<>("Charlie", 78));
for (Pair student : studentScores) {
System.out.println(student.getLeft() + " scored " + student.getRight());
}
}
}
Why use a Pair? A “Pair” makes it easy to store related data in collections.
Graph algorithms (representation of edges)
In graph algorithms, a “Pair” can be used to represent an edge between two nodes.
Example: Representation of a graph edge
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.ArrayList;
import java.util.List;
public class GraphExample {
public static void main(String[] args) {
List> edges = new ArrayList<>();
edges.add(new ImmutablePair<>("A", "B"));
edges.add(new ImmutablePair<>("B", "C"));
edges.add(new ImmutablePair<>("C", "D"));
for (Pair edge : edges) {
System.out.println("Edge: " + edge.getLeft() + " -> " + edge.getRight());
}
}
}
Why use a Pair? It provides a clean way to represent relationships in a graph.
Save coordinates in 2D/3D space
A “Pair” can store x, y (or even x, y, z with a “triple”).
Example: Saving 2D coordinates
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class CoordinateExample {
public static void main(String[] args) {
Pair point = new ImmutablePair<>(10, 20);
System.out.println("Point: (" + point.getLeft() + ", " + point.getRight() + ")");
}
}
Why use a Pair? It simplifies the handling of x, y coordinates.
Caching data with timestamps
A “Pair” can store a value together with its timestamp for caching.
Example: Caching of API results
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class CacheExample {
public static void main(String[] args) {
// Store cached data with timestamp
Pair cachedData = new ImmutablePair<>("weather data", System.currentTimeMillis());
System.out.println("Cached: " + cachedData.getLeft() + " um " + cachedData.getRight());
}
}
Why use a Pair? It enables the linking of metadata with data.
Representation of HTTP headers
A “Pair” can be used to store HTTP headers, which are usually key-value pairs.
Example: Saving HTTP headers
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.ArrayList;
import java.util.List;
public class HttpHeadersExample {
public static void main(String[] args) {
List> headers = new ArrayList<>();
headers.add(new ImmutablePair<>("Content-Type", "application/json"));
headers.add(new ImmutablePair<>("Authorization", "Bearer xyz123"));
headers.add(new ImmutablePair<>("User-Agent", "Mozilla/5.0"));
for (Pair header : headers) {
System.out.println(header.getLeft() + ": " + header.getRight());
}
}
}
Why use a Pair? It simplifies the management of HTTP headers.
Associating metadata with data in logging systems
In logging or monitoring systems, a “Pair” can store a log message together with its log level.
Example: Logging system
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.ArrayList;
import java.util.List;
public class LoggerExample {
public static void main(String[] args) {
List> logs = new ArrayList<>();
logs.add(new ImmutablePair<>("INFO", "Application started"));
logs.add(new ImmutablePair<>("ERROR", "NullPointerException occurred"));
logs.add(new ImmutablePair<>("DEBUG", "User authentication successful"));
for (Pair log : logs) {
System.out.println("[" + log.getLeft() + "] " + log.getRight());
}
}
}
Why use a Pair? It efficiently maps the log levels to the log messages.
Conclusion
In this blog post, we have looked at Java Pair, its various implementations, use cases, best practices and alternatives. Although Pair is a simple and convenient way to store two related values, its use should be carefully considered in terms of readability, maintainability and performance.
Key Takeaways
Here are the key takeaways from our discussion of “Pair” in Java:
Java does not have a built-in Pair
class
- Unlike other languages (e.g. Python’s “Tuple”, Kotlin’s “Pair”), Java does not provide a default implementation of Pair.
- Developers must use third party libraries (such as Apache Commons Lang) or create their own Pair class.
JavaFX’s Pair
is limited
- Found in
javafx.util.Pair
, but requires JavaFX. - it is immutable and has no features like serialization or mutability.
The Pair
from Apache Commons Lang `is more powerful
- Provides
ImmutablePair
andMutablePair
. - Supports serialization, hashing and comparison.
- Recommended for most general use cases.
Creating a custom “Pair” class offers flexibility
- Avoids dependencies and allows own methods such as
swap()
,equals()
andhashCode()
. - Provides better readability when
Pair.getLeft()
andPair.getRight()
are unclear.
Java Records (Java 14+) offer a modern alternative
- Ideal for immutable key-value associations with meaningful field names.
- Generates constructors, getters,
toString()
,equals()
andhashCode()
automatically.
Best practices for the use of Pair
- Use
Pair
for temporal associations or returning multiple values. - Avoid
Pair
if a own class would provide more clarity. - Consider performance and memory usage when choosing between
Pair
, arrays or records.
Common practical applications of Pair
- Return multiple values from one method (e.g. min/max in an array).
- Graph algorithms (representation of edges between nodes).
- Store key value data (e.g. student names and grades).
- Manage HTTP headers, logs and caching with metadata.
Choosing the right approach
When deciding whether to use a “Pair”, you should consider the best alternative for your use case:
Scenario | Recommended approach |
---|---|
Return two values from one method | Pair or Java Record |
Immutable storage of key values | Java Record |
Temporary storage in a list | Pair |
Mutable key value pair | MutablePair (Apache Commons) |
More than two values | Use a custom class or Tuple |
Readability and maintainability | Use a custom class |
Performance optimization | Use arrays if the values are of the same type |
When should you use Java pairs?
Use case | Use Pair ? | Better alternative? |
---|---|---|
Temporary storage of key values | Yes | – |
Returning multiple values | Yes | Java Record (if immutable) |
Graph algorithms (edges) | Yes | – |
Complex objects with more than two fields | No | User-defined class |
Serialization & Storage | Yes | Apache Commons Pair |
Readability is a priority | No | User-defined class or Java Record |
Final thoughts
Since Java does not have a built-in “Pair”, developers must carefully choose the best approach based on readability, performance and maintainability.
- If you need a temporary key-value store,
Pair
is a fast and easy solution. - If you need immutability with better readability, Java Records are the best choice.
- If you need a robust, universal solution, Apache Commons Lang
Pair
is recommended. - If you need extensibility and clarity, creating a custom class is often the best practice.
Understanding the advantages and disadvantages of each approach will help you write cleaner, more maintainable and efficient Java code.

