6 minutes read

In programming, we use functions when we want to perform a certain action, such as calculating the absolute value of a number or identifying a student with the best grades. However, functions have a "little" problem: they only return a value of a particular type. What if we want to return several values of different types? Kotlin offers us two special classes that help us handle this situation: Pair and Triple. Let's see how they work.

Pair

Pair is a simple Kotlin datatype to store two values with the same or different types in a single instance. There doesn't need to be any relationship between the two values. Pair exhibits value semantics, i.e., two pairs are equal if both their components are equal.

To create a new instance of Pair, we use a Pair constructor with the values and types for all data. Kotlin can infer the data type based on the values.

val pair = Pair(1, "one")
println(pair) // (1, one)

We can use the infix function to to create a new Pair object:

val pair = 1 to "one"
println(pair) // (1, one)

How to work with Pair

To work with the values, we can use first and second properties or the componentN method to extract the values from a Pair. The N value of componentN stands for the number of the component; for example, component1 represents the first property or value of a Pair.

val pairOne = Pair("Hi", "I am a Pair")
val pairTwo = "Hi" to "I am another Pair"

// Properties
println(pairOne.first) // Hi
println(pairOne.second) // I am a Pair

// Methods
println(pairTwo.component1()) // Hi
println(pairTwo.component2()) // I am another Pair

With Pair, we can use two special methods – toString() and toList():

  • toString() returns the string representation of the Pair including its first and second values:
val pair = Pair("marks", listOf(8.0, 9.0, 10.0))
println(pair) // (marks, [8.0, 9.0, 10.0]) toString() is implicit
println(pair.toString()) // (marks, [8.0, 9.0, 10.0])
  • toList() converts the Pair into a list:
val pair = Pair("marks", listOf(8.0, 9.0, 10.0))
println(pair.toList()) // [marks, [8.0, 9.0, 10.0]]

Besides, we can use the copy() method to copy Pair objects and change their properties using the name of the parameter (first and second, for example: myCopy = pair.copy(first = "new Value", second = 3)

val pair = Pair("marks", listOf(8.0, 9.0, 10.0))
val other = pair.copy()
println(pair) // (marks, [8.0, 9.0, 10.0])
println(other) // (marks, [8.0, 9.0, 10.0])

With the copy() method, you can also create a new Pair based on another Pair or change some properties. You must preserve the order of properties. Remember: the properties of a Pair are immutable, read-only. You must create a new Pair to change the values, or use the copy function to create a new Pair and assign it whatever values you want based on a previous object.

val pair = Pair("marks", listOf(8.0, 9.0, 10.0))
val other = pair.copy("other")
val grades = pair.copy(second = listOf(9.0, 7.0, 8.5))
val myCopy = pair.copy(first = "other", second = listOf(1.0, 2.0, 3.0))
println(pair) // (marks, [8.0, 9.0, 10.0])
println(other) // (other, [8.0, 9.0, 10.0])
println(grades) // (marks, [9.0, 7.0, 8.5])
println(myCopy) // (other, [1.0, 2.0, 3.0])

Triple

Triple, like Pair, is a simple Kotlin datatype that represents a triad of values with the same or different types in a single instance.
Like in the case of Pair, the type of each property of a Triple object can also be derived from the context.

val triple = Triple(1, "A", true)
println(triple)

How to work with Triple

To work with the values, we can use first, second, and third properties or the componentN method to extract the values. The N value of componentN stands for the number of the component; for example, component1 represents the first property or value of a Triple.

val triple = Triple(1, "I am", "Triple")

// Properties
println(triple.first) // 1
println(triple.second) // I am
println(triple.third) // Triple

// Methods
println(triple.component1()) // 1
println(triple.component2()) // I am
println(triple.component3()) // Triple

Like in the case of Pair, we have two special methods – toString() and toList():

  • toString() returns the string representation of the Triple including its first, second, and third values:
val triple = Triple("marks", "Kotlin", listOf(8.0, 9.0, 10.0))
println(triple) // (marks, Kotlin, [8.0, 9.0, 10.0])
  • toList() converts the Triple into a list:
val triple = Triple("marks", "Kotlin", listOf(8.0, 9.0, 10.0))
println(triple.toList()) //[marks, Kotlin, [8.0, 9.0, 10.0]]

Finally, we can use the copy() method to copy Triple objects:

val triple = Triple("marks", "Kotlin", listOf(8.0, 9.0, 10.0))
val other = triple.copy()
println(triple) // (marks, Kotlin, [8.0, 9.0, 10.0])
println(other) // (marks, Kotlin, [8.0, 9.0, 10.0])

Like in the case of Pair, with the copy() method you can create a new Triple based on another Triple or change some properties. You must preserve the order of properties. Remember: the properties of a Triple are immutable, read-only. You must create a new Triple to change the values, or use the copy function to create a new Triple and assign it whatever values you want based on a previous object.

val triple = Triple("marks", "Kotlin", listOf(8.0, 9.0, 10.0))
val other = triple.copy("other", third=listOf(7.0, 9.0, 8.5))
val course = triple.copy(second = "Kotlin Triple")
println(triple) // (marks, Kotlin, [8.0, 9.0, 10.0])
println(other) // (other, Kotlin, [7.0, 9.0, 8.5])
println(course) // (marks, Kotlin Triple, [8.0, 9.0, 10.0])

Conclusion

Now you know how to easily return two or three values in Kotlin. Remember that in both Pair and Triple, the values can be of different types and that you can easily access them with their properties. Now you can use Pair and Triple to optimize your code without defining wrapper classes in order to work around the limitation of only one value returned by a function. Ready for some questions and tasks? Let's go!

80 learners liked this piece of theory. 2 didn't like it. What about you?
Report a typo