3

I'm trying to do something like this:

 public void <String,int> getItem
 { 
   return <"Jen",23>;
 }

I know I can use a custom class, but how I would I return two results in one function call.

1 - Is the above template function possible in java, and how would by caller get part 1 of it and part 2 later.

2 - Can I do it using an associative array like in actionscript?

3 - Can I do it using a hashmap of some sort?

4 - What are other possible ways are there

I attempted all three ways, but one way or another syntax is hitting me. So if anyone can give clear examples

Alexander Lucas
  • 22,171
  • 3
  • 46
  • 43
airnet
  • 2,565
  • 5
  • 31
  • 35
  • you make a simple class wrapper, then instantiate on and return it... is there a reason not to do it this way? – Randy Feb 17 '12 at 23:06
  • No, you can't return two things from a method. Even scripting languages that pretend like you can are wrapping said things in a list or an array. – Brian Roach Feb 17 '12 at 23:07
  • just playing around, and understanding programming lingo – airnet Feb 17 '12 at 23:23

8 Answers8

10

Java functions always return a single value, so your only option is to return a "collection" object which contains multiple values, such as an Array or a proper Collection. For example:

public Object[] getItem() { return new Object[] { "Jen", 23 }; }
public Collection<Object> { return Arrays.asList("Jen", 23); }

Although, a typical pattern in Java is to return a custom type which encapsulates your values, e.g.:

public class NameAge {
  public final String name;
  public final int age;
  public NameAge(String name, int age) {
    this.name = name;
    this.age = age;
  }
}
// ...
public NameAge getItem() { return new NameAge("Jen", 23); }

Or more generally:

public class Pair<X, Y> {
  public final X x;
  public final Y y;
  public Pair(X x, Y y) {
    this.x = x;
    this.y = y;
  }
}
// ...
public Pair<String,Integer> getItem() {
  return new Pair<String,Integer>("Jen", 23);
}

Of course, there are serious implications regarding hashing (equality and hash code) if you want to use these custom types as hash keys.

maerics
  • 151,642
  • 46
  • 269
  • 291
4

I like using generics! Create your own class and return an instance of it:

public class Tuple<T,V>
{
  public T item1;
  public V item2;
  public Tuple(T i1, V i2)
  { 
     item1 = i1;
     item2 = i2;
  }
}

Then you create your method:

public Tuple<String, int> getItem()
{
   return new Tuple<String, int>("Jen", 23);
}
Diego
  • 18,035
  • 5
  • 62
  • 66
1

Java does not allow for multiple return statements. The best practice I believe is to create a custom object. What you have here suggests some sort of Person class, a la

public class Person {
  int Age;
  String Name;
}

Returning an object will make it more intuitive what you are doing as well.

smessing
  • 4,330
  • 1
  • 22
  • 19
1

You can return a Bundle.

public Bundle getItem(){
   Bundle theBundle = new Bundle();
   theBundle.putString("name","Jen");
   theBundle.putInt("age",23);
   return theBundle;
}
danielrozo
  • 1,442
  • 1
  • 10
  • 22
  • nice :), glad you gave this answer. I wish I could give u a point as well – airnet Feb 20 '12 at 06:11
  • You wouldn't use a Bundle, unless you need the functionality specific to Bundle. Instead use ArrayMap (which Bundle is built on) for small number of items. Or for maximum efficiency, use SimpleArrayMap, if its limited container functionality is sufficient. Or if you have hundreds of items to return, use HashMap. – ToolmakerSteve Jun 17 '14 at 23:52
1

The proper way would be to create a class for your return set:

public class ReturnSet {
    private String str;
    private int num;

    public ReturnSet(String _str, int _num) {
        str = _str;
        num = _num;
    }

    //add getters and setters
    ...
}

Then your function would look like

public ReturnSet getItem() {
    ...
    return new ReturnSet(strValue, intValue);
}

Of course, you can fudge things by having your function return an array of Object, but this would be a rather bad code:

public Object[] getItem() {
    Object[] result;
    //allocate it, get data;
    ...
    result[1] = strValue;
    relult[2] = new Integer(intValue);
    return result;
}

You can even return a hashmap with one element in it:

public Map getItem() {
    Map result;
    //allocate it, say as hashmap, get data;
    ...
    result.put(strValue, new Integer(intValue));
    return result;
}

Then in the caller, the key of the map would be the first part and the value would be the second.

While there are may be many ways of doing things like that, the first one is the right approach.

Aleks G
  • 56,435
  • 29
  • 168
  • 265
1

Usually, if you need to return two values from one function - it's a code smell. Try to refactor your code so that every function always return just one value. Keep in mind that no return value (void) is also a code smell, but less critical.

yegor256
  • 102,010
  • 123
  • 446
  • 597
  • I strongly disagree. What is important in designing the API of a class, is matching the tasks that clients of the class need to do. Factoring to return just one value per method is counter-productive. Worse, it usually results in an API that mirrors internals of the object, because that is the easiest way to return one value at a time. Don't go down this road. On the other hand, defining new internal classes to wrap multiple values, rather than using some general-purpose Tuple solution, I would agree with. So a refactoring that creates such classes, I agree is a reduction in code smell. – ToolmakerSteve Jun 17 '14 at 23:29
0

You can also return one value the regular way and other(s) by using a "return" parameter:

class C {
    Type2 value; // omitted getter and setter for brevity
}
Type1 f1(C returnParameter, String otherParameters...)
{
    // function body here
    returnParameter.value=returnValue2; // store the second result
    return returnValue1; // return the first result
}

// usage
Type1 result1;
Type2 result2;
C helper = new C();
result1=f1(helper, "foo", "bar");
result2=helper.value;

For more results either use several "helper" objects or one that can hold several values.

I am myself looking for a most elegant solution (in my case one return type is a Collection and the other is an integer number-any variant of it is OK).

David Balažic
  • 1,319
  • 1
  • 23
  • 50
  • ALMOST merits -1. Don't do this, unless you have a strong reason to do so. Some other languages have a good syntax that make return parameters clear, and reasonable to use. Java does not. In Java, it is clearer if you define a new class to hold all the return values, and return a new object holding them. As shown in other answers. – ToolmakerSteve Jun 17 '14 at 23:41
  • HOWEVER there **IS** an OPTIMIZATION situation where return parameters make sense: a method that is called many, many times, and a caller that can re-use the same parameters on each call. To avoid creating temporary object per call. In this case, make the return type void -- return ALL the results as return parameter(s). And add a **DOC COMMENT** to the method, explaining correct usage of such parameter(s). – ToolmakerSteve Jun 17 '14 at 23:44
0

If a method returns something, then its return type must be this something:

public MyCustomObject getItem();

or

public Object[] getItem():

or anything else wher you can store the results.

But Java is a statically typed OO language. A custom class is the way to go.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255