1. Overview

Kotlin is a language that brings us exciting features. The Pair class represents a generic pair of two values, and it can be helpful in many situations. For example, when we have to return two values in a function.

In this quick tutorial, we’ll look at how Pair works in Kotlin.

2. Pair Class

First of all, here’s the Pair class definition:

public data class Pair<out A, out B>(
    public val first: A,
    public val second: B
) : Serializable

There are two parameters, A and B, that represent the types of the two values, called first and second.

2.1. Constructors

In the class definition, we can notice that Pair is a data class. Therefore, it has a constructor that receives both the first and second parameters.

These properties can be accessed, but they aren’t modifiable as they’re defined as val:

val pair = Pair(first = 1, second = "value")
assertEquals(1, pair.first)
assertEquals("value", pair.second)
pair.first = 2 // won't work

Another way to create a Pair is using the infix function. Here’s the function declaration:

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

Using the infix function results in a very natural language:

val pairInfixFunction = 1 to "value"
assertTrue(pairInfixFunction is Pair)

2.2. Usage

Since it’s a data class, Pair provides us functions like a toString() that prints values in a human-readable way:

val pairToString = Pair(first = "Hello", second = "World")
assertEquals("(Hello, World)", pairToString.toString())

And equals() makes it easy to compare Pair values:

val pair = Pair(first = 1, second = "value")
val otherPair = Pair(first = 1, second = "value")
assertTrue(pair == otherPair)

Also, there’s a convenient way to destructure a Pair into two variables:

val pair = Pair(first = 1, second = "value")
val (first, second) = pair
assertEquals(1, first)
assertEquals("value", second)

It’s worth noting that it isn’t obligatory to use the properties first and second as variable names.

Pair uses generic types as properties so that we can use any kind of object as values:

val pairOfObjects = Pair(first = listOf("one","two"), second = IntRange(start = 1, endInclusive =  10))
assertEquals("([one, two], 1..10)", pairOfObjects.toString())

2.3. Extension

There’s a built-in Kotlin extension for Pair. The toList() function easily converts a Pair into a read-only List with the two Pair values. We can then use any List function:

val pair = Pair(first = "Hello", second = "World") 
val listFromPair = pair.toList() 
assertTrue(listFromPair is List<String>)
assertEquals(2, listFromPair.size)
assertEquals("World", listFromPair.sortedDescending().first())

3. Using Pair in Map

A useful application for the Pair class is in the Map interface implementations. There are many top-level functions, but for this article, let’s focus on the mapOf() function:

val mapOfPairs = mapOf(1 to "one", 2 to "two", 3 to "three")
assertEquals("{1=one, 2=two, 3=three}", mapOfPairs.toString())

In Map structures, the first property represents a key, and the second property represents the value, so we can get any second by the first value:

assertEquals("one", mapOfPairs[1])
assertEquals("two", mapOfPairs[2])
assertEquals("three", mapOfPairs[3])

This structure overrides any Pair with the same first property:

val mapOfPairs = mapOf(1 to "one", 2 to "two", 1 to "three")
assertEquals(2, mapOfPairs.size)
assertEquals("three", mapOfPairs[1])

4. Conclusion

In this article, we’ve learned the use of Pair in Kotlin. It’s a useful class for different situations, like returning a couple of values in a function or creating a Map.

Since it’s generic, it’s very important to pay attention to its usage. It wasn’t made to replace objects with two properties but to pair objects in an easy and clean way. That being said, it provides some interesting functionality and very easy usage.

All code in this article is available over on GitHub.

Comments are closed on this article!