56

Why isn't there a (standard, Java certified) solution, as part of the Java language itself, to return multiple values from a Java method, rather than developers having to use their own means, such as Maps, Lists, Pairs, etc.? Why does Java not support n-tuple objects?

Especially thinking for trivial private methods that may modify two objects together (in tandem), and in which case a typed-object as a return sounds overkill.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Saket
  • 45,521
  • 12
  • 59
  • 79
  • 4
    Hm.............? Using such data structures _is_ the standard, no? – mrkhrts Sep 19 '11 at 12:24
  • Because nobody's done the work to take one of those custom solutions and standardize it, of course! – Donal Fellows Sep 19 '11 at 12:24
  • 12
    There is a standard way: it's called an object. – toto2 Sep 19 '11 at 12:25
  • yes, those are standard data structure, but aren't there ways to put it as part of the language construct rather than wrapping it within collections? a simple analogy, if I may, is that you could pass in multiple arguments to a method in two ways: (a). Have a single parameter variable which is a List> and extract individual params from it or (b). have different parameter variables for each argument. Just thinking out loud... – Saket Sep 19 '11 at 12:28
  • What you're trying to do is non-standard. Standard approaches include using maps, lists or custom objects! – adarshr Sep 19 '11 at 12:30
  • @adarshr - perhaps it sounds 'non-standard' because there is no standard as such **yet**, which is what am trying to look for :) Again, I'm just trying to open up the discussion. – Saket Sep 19 '11 at 12:32
  • Possible duplicate of http://stackoverflow.com/questions/457629/how-to-return-multiple-objects-from-a-java-method – Raedwald Sep 19 '11 at 12:43
  • I did see the above post, which talks about **how** to do this. But what I'm trying to open up is why should such means be needed. – Saket Sep 19 '11 at 12:45
  • "I'm just trying to open up the discussion": discussions are not the recommended style here. See http://stackoverflow.com/faq#dontask – Raedwald Sep 19 '11 at 12:46
  • @Raedwald - 'discussion'...not literally :) . I'm trying to (along with may be some others as well) understand/learn the theory behind it. – Saket Sep 19 '11 at 12:48
  • See also: http://stackoverflow.com/questions/457775/does-java-need-tuples – Raedwald Sep 19 '11 at 12:51
  • Maybe java is doing it to force you to use "named" style return values, so there is no confusion as to what is begin returned... – rogerdpack Apr 16 '13 at 20:05
  • Other languages do this by having a pass-by-reference syntax (or a pseudo pass-by-reference, like using & (address operator) in C or C++. That was the way people got around it "back in the old days". I'm trying to decide how to do this for something and I may chose the private static class explained below as the selected answer. – titania424 Oct 09 '13 at 16:27
  • Why not create your own Tuple class like in [this question](https://stackoverflow.com/questions/16867158/return-tuple-from-java-method) ? – jk7 Jan 10 '18 at 19:04

7 Answers7

66

I assume the OP means "Why does Java not support n-tuple objects?". Python, Haskell, Lisp, ML etc have heterogeneous n-tuple capabilities. Also often times the ability to apparently return multiple objects in a language is syntactical sugar (ie in python return 'a','b').

The reason of course is language design and consistency. Java prefers being very explicit and does not like anonymous data structures (although I wish we had anonymous closures).

For example in Java there is no way to say I would like a callback that takes these type parameters and returns this. Some people feel this a huge weakness others like the consistency and explicitness.

IMHO although its annoying I frequently combat this issue by making static inline classes:

private static class Combo {
   String name;
   int weight;
}

Yes its tedious but then later on I often reuse and refactor those classes making them top level and adding behavior. Infact one of the advantages with going this route is that its much easier to add new fields where is the anonymous data structure (like in FP languages) it becomes much more difficult to add a field (you end up changing a ton of code).

I should note that for 2-tuples some people use (or abuse) java.util.Map.Entry as there is an java.util.AbstractMap.SimpleEntry in Java 6. Also Some people now use Commons Lang3's Pair support (2-tuple).

Scala has n-tuple support by sort of cheating and having a whole bunch of 2-16 tuple interfaces that are standard in the language and are syntactically hidden from the programmer.

For purely educational reasons you may want to see how other languages accomplish this.

UPDATE: for Java 8

Java 8 will/maybe (so heres my number... call me maybe) support an interface called java.lang.BiValue with a concrete implementation that you can use called java.lang.BiVal . These classes are to help support the new lambda functionality. But notice this is only for 2-tuples.

UPDATE: for 2015

Java 8 did not gain support for tuples.

UPDATE: from author 2015

If you still would like tuple support there are three libraries that support tuples well:

  • javatuples - Supports JDK 5 and above. Up to 10-tuple.
  • JOOλ - From the author of jOOQ but requires JDK 8.
  • Commons Lang 3 - Now supports a Triple (3-tuple) and supports JDK 6 and above.
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • 11
    Map.Entry is my favorite. Why create a named object for a simple task that other languages do on the fly? – Erel Segal-Halevi Feb 26 '13 at 08:15
  • There could be concurrency issues with this pattern (safe publication). The pattern described in [this answer to a similar question](http://stackoverflow.com/a/457642/372643) (`final` + constructor) should address this problem. – Bruno Oct 10 '13 at 11:45
  • Yes I only put the above for brevity and not for full reuse. Immutable objects are always a good choice. – Adam Gent Oct 10 '13 at 13:32
  • What if I have to return 3 objects? – Dejell Dec 17 '13 at 12:32
  • 3
    +1 for going back and actually updating the answer in the face of changing conditions. I wish more people did this. – Chris Warth Jun 12 '15 at 00:30
  • I'm not seeing `java.lang.BiValue` built into Java 8 as above suggested. Maybe remove mentioning it. – matanster Apr 05 '18 at 13:27
10

Java methods return exactly zero or one value; that is the standard for java. If you need multiple values returned, create an object with the multiple values and return it.

DwB
  • 37,124
  • 11
  • 56
  • 82
6

If you want to return two objects you usually want to return a single object that encapsulates the two objects instead.

5

There are plenty of hackish ways to accomplish this, one way would be to return an Object[], but then you've got indices to worry about, and null pointer checks, it just gets nasty. Another way is to return a String, but then you've got to parse it, and it gets nasty.

I think the real question is why?

Here's the rub - If I were working on a project with you, and I saw this type of behavior, I'd rewrite it so you could see how it should be handled. If you provide a code sample, I'll rewrite it to illustrate.

Write your methods with a single responsibility, if they need to return more data than they have the ability to, you should likely either use an object, or break it into smaller methods.

Travis
  • 3,737
  • 1
  • 24
  • 24
  • Good argument with the single responsability – Wivani Sep 19 '11 at 12:59
  • 1
    using an object and breaking into smaller methods are very good approaches as explained in the answer. – Jayy Sep 19 '11 at 13:44
  • @Travis let's say we have a disk cache object with a method that returns both cached value and its annotations (e.g. last modified time). Multiple return values is much cleaner that using a wrapper object. We can't use two method calls, because the cache can change between the method calls. – fhucho Mar 16 '13 at 10:19
  • @fhucho This is a case where it would apply, that makes sense. What you're looking for is the last write and its details/metadata. Why should this not be encapsulated in an object? – Travis Mar 18 '13 at 19:55
  • 1
    @Travis I think it would result in slightly cleaner and easier to understand code. Also, no need for a wrapper class. But this is a matter of opinion I guess. – fhucho Mar 18 '13 at 23:06
2

There is a new style of pattern available, and fits in with the "all asynchronous" nature that you might see in languages such as JavaScript.

A lot of my code looks like this nowadays :-)

public class Class1 {

    public interface Callback {
       void setData(String item1, String item2);
    }
    public void getThing(Callback callback) {
        callback.setData("a", "b");
    }
}

public class Class2 {

    public void doWithThing(Class1 o) {
        o.getThing(new Class1.Callback() {
            public void setData(String item1, String item2) {
                ... do something with item 1 and item 2 ...
            }
        });
    }

}

No new objects to create and not that many extra classes since the interface is an inner class of the object.

This is what makes Swift so awesome. The code can look like this:

o.getThing({ item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
});

And since the only argument is the block, even this:

o.getThing { item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
};

Java needs work to make callback laden code a lot easier to read.

2

Because returning multiple value from a method is not a recommended practice ( in Java ).

If you need unrelated values from a method you need a different datastructure like an object containing those values. If you need multiple instances of the same class ( ie several Strings ) you need to return either an array, or some collection depending on your needs.

Returning multiple values in other languages ( Go for instance ) are used for instance to return an eror code, but Java was designed differently using exceptions.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
0

I felt myself the need to return multiple values. And I was looking for a "pair" or "tuple" value. But after that, I've seen how I use the return type:

// scala
tuple(0)
tuple(1)

What 0 and 1 means and in which order? I think it is better to be explicit about what they mean. Create a small static class inside the object containing the method.

Just an example that comes into my mind. Maybe not the best:

public class SomeClass {
    
    public TimeInterval getValability(Voucher voucher) {
        .....
    }
    
    //value objects should be immutable
    public static class TimeInterval {
        public final LocalDate startDate;
        public final LocalDate endDate;
        private TimeInterval(LocalDate startDate, LocalDate endDate) {
            this.startDate = startDate;
            this.endDate = endDate;
        }
    }

}

then the person reading the code understand the result of the function:

TimeInterval interval = someClassInstance.getValability(voucher);
if(interval.startDate ......

instead of:

// from https://www.javatuples.org/
Pair interval = someClassInstance.getValability(voucher);
if(interval.getValue0() ......

I don't know your use case, but maybe your function is doing two things (Single Responsibility Principle)?

Edited:

Or maybe this example that I've found in my code will be more realistic:

@AllArgsConstructor
@Getter
public static class ResponseStatus {
    private final boolean isFailed;
    private final String failureReason;
}

with usage:

if (responseStatus.isFailed()) {
    customerHttpResponse.setAsFailed();
    customerHttpResponse.setResponseBody(responseStatus.getFailureReason());
    .....
}

In that way the client code is easier to read in my opinion.

Mihai
  • 56
  • 1
  • 4