tags:

views:

5770

answers:

11

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.

+14  A: 

If you want to return two objects you usually want to return a single object instead, 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.

Joachim Sauer
The reason for returning comma separated list is: If I dont create the list here, I would have to do this in the caller by looping through the objects (CS value is needed). Perhaps, I am pre-optimizing unnecessarily.
Jagmal
I've always wondered why Java doesn't have a Pair<T, U> class for this reason.
David
Jagmal: yes, if the only rason for returning the comma-separated list is this optimization, then forget about it.
Joachim Sauer
This only works well if the items you'd like to return are of the same class, or at least have a close common ancestor. I mean, using Object in place of WhateverTypeYouWant isn't very neat.
David Hanak
@David: I agree that using Object here isn't very neat, but then again return objects without any common ancestor (except Object of course) isn't very neat as well. I'd even say it's a code smell, if you need that.
Joachim Sauer
A: 

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.

Bombe
I agree with you on this but if I do so, I will end up looping twice (I am actually creating the elements of list one-by-one in the existing method).
Jagmal
@Jagmal: you might loop twice, but it doesn't matter most of the time (see gizmos answer).
Joachim Sauer
Yeah, don’t try to optimize your code unless you really have to. gizmo is very right about that.
Bombe
+3  A: 

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.

kipz
This won't work if any of the names collide. A list could contain duplicates, but a Map can't (contain duplicate keys).
tvanfosson
Of course. I was making assumptions based on the question - perhaps unduely :)
kipz
Although your assumption holds true in this case, I am walking into the domain of premature optimization (which I should not do).
Jagmal
+2  A: 

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

D. Knuth

gizmo
I think the OP was not asking about performance, but rather about the correct style, the idiomatic way.
Joachim Sauer
Asking for returning multiple objects to avoid a loop after IS thinking about "optimization". More over, if we could have a more global context about the incoming arguments, we could provide better answers, not with the actual question.
gizmo
Oh, you meant that optimization, I missed that. You're right.
Joachim Sauer
I agree w/ gizmo. Perhaps, I should not think of optimizing at this point.
Jagmal
@Jagmal -- if you have to calculate the name string in two places, then you should move it into a single method somewhere in keeping with the DRY principle. The second time you need to do this calculation is the time to think of it, though, not the first.
tvanfosson
@tvanfosson: Bingo. Actually, I dont need to calculate name in "this" method but since I was looping through objects and would definitely need the name in the caller, I wanted to be 'optimum' (since the current method is private only). But, I guess I know the general opinion.
Jagmal
+1  A: 

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.

tvanfosson
A: 

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.

kgiannakakis
+4  A: 

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;
    }
};
David Hanak
I usually have this class knocking about in each codebase I work on. I'd also add: a hashCode/equals implementation, and possibly a static isInstance() and cast() method.
jamesh
Sure, there are many ways to make this class smarter and more convenient to use. The version above includes what's just enough in a one-shot declaration.
David Hanak
+3  A: 

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.

Ulrik Rasmussen
+1  A: 

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 );
    }
}
A: 

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:

  1. These results objects are intimately tied together/related and belong together, or:
  2. 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.

Brian Agnew
A: 

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

public void buildResponse(String data, Map response);

l_39217_l