Skip to main content

How to return multiple objects from a Java method?



I want to return two objects from a Java method and was wondering what could be a good way of doing so?





The possible ways I can think of are: return a HashMap (since the two Objects are related) or return an ArrayList of Object objects.





To be more precise, the two objects I want to return are (a) List of objects and (b) comma separated names of the same.





I want to return these two Objects from one method because I dont want to iterate through the list of objects to get the comma separated names (which I can do in the same loop in this method).





Somehow, returning a HashMap does not look a very elegant way of doing so.


Comments

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

    You could return a List of NamedObject objects like this:

    public class NamedObject<T> {
    public final String name;
    public final T object;

    public NamedObject(String name, T object) {
    this.name = name;
    this.object = object;
    }
    }


    Then you can easily return a List<NamedObject<WhateverTypeYouWant>>.

    Also: Why would you want to return a comma-separated list of names instead of a List<String>? Or better yet, return a Map<String,TheObjectType> with the keys being the names and the values the objects (unless your objects have specified order, in which case a NavigableMap might be what you want.

    ReplyDelete
  2. If you know you are going to return two objects, you can also use a generic pair:

    public class Pair<A,B> {
    public final A a;
    public final B b;

    public Pair(A a, B b) {
    this.a = a;
    this.b = b;
    }
    };


    Edit A more fully formed implementation of the above:

    package util;

    public class Pair<A,B> {

    public static <P, Q> Pair<P, Q> makePair(P p, Q q) {
    return new Pair<P, Q>(p, q);
    }

    public final A a;
    public final B b;

    public Pair(A a, B b) {
    this.a = a;
    this.b = b;
    }

    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((a == null) ? 0 : a.hashCode());
    result = prime * result + ((b == null) ? 0 : b.hashCode());
    return result;
    }

    @Override
    public boolean equals(Object obj) {
    if (this == obj) {
    return true;
    }
    if (obj == null) {
    return false;
    }
    if (getClass() != obj.getClass()) {
    return false;
    }
    @SuppressWarnings("rawtypes")
    Pair other = (Pair) obj;
    if (a == null) {
    if (other.a != null) {
    return false;
    }
    } else if (!a.equals(other.a)) {
    return false;
    }
    if (b == null) {
    if (other.b != null) {
    return false;
    }
    } else if (!b.equals(other.b)) {
    return false;
    }
    return true;
    }

    public boolean isInstance(Class<?> classA, Class<?> classB) {
    return classA.isInstance(a) && classB.isInstance(b);
    }

    @SuppressWarnings("unchecked")
    public static <P, Q> Pair<P, Q> cast(Pair<?, ?> pair, Class<P> pClass, Class<Q> qClass) {

    if (pair.isInstance(pClass, qClass)) {
    return (Pair<P, Q>) pair;
    }

    throw new ClassCastException();

    }

    }


    Notes, mainly around rustiness with Java & generics:


    both a and b are immutable.
    makePair static method helps you with boiler plate typing, which the diamond operator in Java 7 will make less annoying. There's some work to make this really nice re: generics, but it should be ok-ish now. (c.f. PECS)
    hashcode and equals are generated by eclipse.
    the compile time casting in the cast method is ok, but doesn't seem quite right.
    I'm not sure if the wildcards in isInstance are necessary.
    I've just written this in response to comments, for illustration purposes only.

    ReplyDelete
  3. I almost always end up defining n-Tuple classes when I code in Java. For instance:

    public class Tuple2<T1,T2> {
    private T1 f1;
    private T2 f2;
    public Tuple2(T1 f1, T2 f2) {
    this.f1 = f1; this.f2 = f2;
    }
    public T1 getF1() {return f1;}
    public T2 getF2() {return f2;}
    }


    I know it's a bit ugly, but it works, and you just have to define your tuple types once. Tuples are something Java really lacks.

    EDIT: David Hanak's example is more elegant, as it avoids defining getters and still keeps the object immutable.

    ReplyDelete
  4. Before Java 5, I would kind of agree that the Map solution isn't ideal. It wouldn't give you compile time type checking so can cause issues at runtime. However, with Java 5, we have Generic Types.

    So your method could look like this:

    public Map<String, MyType> doStuff();


    MyType of course being the type of object you are returning.

    Basically I think that returning a Map is the right solution in this case because that's exactly what you want to return - a mapping of a string to an object.

    ReplyDelete
  5. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.


    D. Knuth

    ReplyDelete
  6. Alternatively, in situations where I want to return a number of things from a method I will sometimes use a callback mechanism instead of a container. This works very well in situations where I cannot specify ahead of time just how many objects will be generated.

    With your particular problem, it would look something like this:

    public class ResultsConsumer implements ResultsGenerator.ResultsCallback
    {
    public void handleResult( String name, Object value )
    {
    ...
    }
    }

    public class ResultsGenerator
    {
    public interface ResultsCallback
    {
    void handleResult( String aName, Object aValue );
    }

    public void generateResults( ResultsGenerator.ResultsCallback aCallback )
    {
    Object value = null;
    String name = null;

    ...

    aCallback.handleResult( name, value );
    }
    }

    ReplyDelete
  7. As I see it there are really three choices here and the solution depends on the context. You can choose to implement the construction of the name in the method that produces the list. This is the choice you've chosen, but I don't think it is the best one. You are creating a coupling in the producer method to the consuming method that doesn't need to exist. Other callers may not need the extra information and you would be calculating extra information for these callers.

    Alternatively, you could have the calling method calculate the name. If there is only one caller that needs this information, you can stop there. You have no extra dependencies and while there is a little extra calculation involved, you've avoided making your construction method too specific. This is a good trade-off.

    Lastly, you could have the list itself be responsible for creating the name. This is the route I would go if the calculation needs to be done by more than one caller. I think this puts the responsibility for the creation of the names with the class that is most closely related to the objects themselves.

    In the latter case, my solution would be to create a specialized List class that returns a comma-separated string of the names of objects that it contains. Make the class smart enough that it constructs the name string on the fly as objects are added and removed from it. Then return an instance of this list and call the name generation method as needed. Although it may be almost as efficient (and simpler) to simply delay calculation of the names until the first time the method is called and store it then (lazy loading). If you add/remove an object, you need only remove the calculated value and have it get recalculated on the next call.

    ReplyDelete
  8. All possible solutions will be a kludge (like container objects, your HashMap idea, “multiple return values” as realized via arrays). I recommend regenerating the comma-separated list from the returned List. The code will end up being a lot cleaner.

    ReplyDelete
  9. In C++ (STL) there is a pair class for bundling two objects. In Java Generics a pair class isn't available, although there is some demand for it. You could easily implement it yourself though.

    I agree however with some other answers that if you need to return two or more objects from a method, it would be better to encapsulate them in a class.

    ReplyDelete
  10. Why not create a WhateverFunctionResult object that contains your results, and the logic required to parse these results, iterate over then etc. It seems to me that either:


    These results objects are intimately tied together/related and belong together, or:
    they are unrelated, in which case your function isn't well defined in terms of what it's trying to do (i.e. doing two different things)


    I see this sort of issue crop up again and again. Don't be afraid to create your own container/result classes that contain the data and the associated functionality to handle this. If you simply pass the stuff around in a HashMap or similar, then your clients have to pull this map apart and grok the contents each time they want to use the results.

    ReplyDelete
  11. PASS A HASH INTO THE METHOD AND POPULATE IT......

    public void buildResponse(String data, Map response);

    ReplyDelete
  12. public class MultipleReturnValues {

    public MultipleReturnValues() {
    }

    public static void functionWithSeveralReturnValues(final String[] returnValues) {
    returnValues[0] = "return value 1";
    returnValues[1] = "return value 2";
    }

    public static void main(String[] args) {
    String[] returnValues = new String[2];
    functionWithSeveralReturnValues(returnValues);
    System.out.println("returnValues[0] = " + returnValues[0]);
    System.out.println("returnValues[1] = " + returnValues[1]);
    }

    }

    ReplyDelete

Post a Comment

Popular posts from this blog

Why is this Javascript much *slower* than its jQuery equivalent?

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...

Is it possible to have IF statement in an Echo statement in PHP

Thanks in advance. I did look at the other questions/answers that were similar and didn't find exactly what I was looking for. I'm trying to do this, am I on the right path? echo " <div id='tabs-".$match."'> <textarea id='".$match."' name='".$match."'>". if ($COLUMN_NAME === $match) { echo $FIELD_WITH_COLUMN_NAME; } else { } ."</textarea> <script type='text/javascript'> CKEDITOR.replace( '".$match."' ); </script> </div>"; I am getting the following error message in the browser: Parse error: syntax error, unexpected T_IF Please let me know if this is the right way to go about nesting an IF statement inside an echo. Thank you.