What's the best way to return a pair of values in Java?

JavaData Structures

Java Problem Overview


This is a small issue, as I could easily whip up a pair class to do the job. I don't really want to do this though, and I feel like there should be some simple, built-in, java-like way of returning two values. What do you guys is the best, simplest way of doing this? Arrays? Some other data structure?

Java Solutions


Solution 1 - Java

As far as I know, there is unfortunately no built-in representation of a pair in Java (and I certainly wish there was). Personally, when I code a project where I find that a pair class often would be useful, I create a generic Pair<T, U> class (which is probably what you were thinking of). Returning an array is a fast and simple way, but you might come to regret it later, because people who use your method will wonder whether the method might at some point return more than two values.

Whichever solution you choose: whenever you feel that you need a Pair, you should consider whether the time saved today by using e.g. a generic Pair class really is worth the loss of information to the next person who reads the code (and that person may well be you in six months). Writing a separate class for the return type takes more time now, but it would convey more information to those that use your method (namely, it tells the users what the return value represents, and contains useful member names for the two values). If it is a non-public method that is used only a few places, though, a Pair is more acceptable.

Solution 2 - Java

Using a container class is the easiest way.

 public class Pair<T, U> {         
    public final T t;
    public final U u;
     
    public Pair(T t, U u) {         
        this.t= t;
        this.u= u;
     }
 }

Solution 3 - Java

The closest thing I've seen to a "pair" in the standard libraries are the Map.Entry interface and the AbstractMap.SimpleEntry and AbstractMap.SimpleImmutableEntry classes that implement it.

If both objects are the same class an array is easier to use.

Solution 4 - Java

Apache Commons Lang3 provides an abstract Pair class with a couple implementations including ImmutablePair and MutablePair.

Solution 5 - Java

Three approaches, all not so great:

  1. Roll your own Pair<A, B>. You said you didn't want to do that.
  2. Return a Object[]. This is not type safe.
  3. Mimic out variables or pointers by supplying single element arrays as parameters.

An example of #3:

public boolean getUserDetails(String userId, String[] lastName, String[] firstName, Date[] dob) {
  assert lastName  != null && lastName.length  == 1;
  assert firstName != null && firstName.length == 1;
  assert dob       != null && dob.length       == 1;
  ...
}

The third option makes life painful for the caller.

So like I said, no nice solution.

As an aside, Scala uses various Tuple classes (up to 21-tuple, from what I remember) to help you with this.

Solution 6 - Java

There is a pair class in JavaFX, but you shouldn't use it. What you SHOULD use is something like this:

// We've skipped imports and package declarations
public final class YourClass {
  /* Assume there is a bunch of stuff here */
  
  // I don't know what method you're using, so forgive the silly example
  public YourClass.Pair sillyExampleOfPairs(String someString) {
    return new YourClass.Pair(someString, someString.length() * 13);
  }

  @Value // Lombok annotation.
  public static class Pair {
    String text;
    int integer;
  }

  // this is an even more succinct possibility
  @Value public static final class ShorterPair {String text; int integer}
}

While the name Pair here is obviously not that well chosen, and you should choose a more descriptive name, the obvious ways this will work (the fields are final private and you have a getter on each, because of the annotation), should not be lost on you. And while yes, this is slightly more wordy than using Pair, it's much more robust. What if you do need to add an extra parameter to the return value? You "only" need to change this class then. And you can update all the relevant JavaDocs immediately, which is also nice. If you have to change types, they would both entail similar amounts of work.

As long as you're only adding stuff, the old getText() and getInteger() methods would keep working as they did before. You also avoid having to add Yet Another Dependency to your projects. It's not a big win. Having Pair available is nice for prototyping, but it's not nice for later.

My final theoretical CS-y argument is that Pair is the same type as Pair. But if you have a Phonebook.Entry (with String and int) and say, Inventory.Item (with a name and a number of items we currently have inventoried), these two are very distinct types, which do very distinct things. You can't put one into the other. This is a Good Thing.

It's also much clearer for us poor bastards that have to go and debug your systems to see something like "com.name.project.something.something.Phonebook.Entry" in a stack trace than "org.apache.commons.lang3.tuple.Pair". One of these tells me WHAT I'm supposed to be looking at, and gives me some info on WHY I'm seeing a pair. The other says... nothing.

Now you might not care that you have to type for 3 extra seconds to save me 3 minutes. But I choose to believe in the goodness of your heart, and the nobility of your soul. Therefore, do the right thing.

Write a small static class instead.

Solution 7 - Java

I have been told by experts that when faced with the question of pairs, one of two things is true:

  1. You need to rethink your structure (this blunt answer doesn't help anyone)
  2. You need to build your own class to hold the pair

I would suggest that the second case is not all that abnormal. However, if what you are doing seems too trivial for introducing a new class, then using a Map could work, as others have suggested. If you are simply sending a single response back, then a Map seems like a bit much.

If a list of pairs sounds like it would work, and you need to maintain order, you could try a LinkedHashMap so that order is maintained.

Solution 8 - Java

if both are integers then I would advise a java.awt.Point but otherwise just create a container class with two objects x and y

Solution 9 - Java

Some observation of mine:

  1. Array is bulit-in, fast and easy to use, although imposible to expand its capacity. What if you want 3 values to be returned after 3 months?

  2. ArrayList/other colletions can be good, allows you to increment the capacity(initially 10). Note that Vector can be overkill in comparison to ArrayList when you only want to store 2 values to be fetched later. Map also can be good because it's always sorted and ordered.

  3. Some user-defined class: maybe an option if is meaningful(means that the data returned is important-ish to be a Java Bean), and you want to store more than just 2 integers into it. Readibility is better in case you add more notes in its Javadoc. Can be expanded as you like, just add fields in this class. Slower, but safer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGrahamView Question on Stackoverflow
Solution 1 - JavaAasmund EldhusetView Answer on Stackoverflow
Solution 2 - JavaHzyfView Answer on Stackoverflow
Solution 3 - JavatruthealityView Answer on Stackoverflow
Solution 4 - JavaJohnGlynnView Answer on Stackoverflow
Solution 5 - JavaDilum RanatungaView Answer on Stackoverflow
Solution 6 - JavaHaakon LøtveitView Answer on Stackoverflow
Solution 7 - JavaTanner PerrienView Answer on Stackoverflow
Solution 8 - Javaif_zero_equals_oneView Answer on Stackoverflow
Solution 9 - JavaWesternGunView Answer on Stackoverflow