2

What are (1) the common practice and (2) possible solutions for returning a pair of objects in one method in java?

Example: Let's say I have a CheckersBoard class in Model that has a method f that takes BoardFieldIndex start, BoardFieldIndex end describing a movement asked by a View and returns a pair of Figure f (if start is occupied) and MovementVector v (if it is legal on the board).

In C++ I have two popular options:

(I.)

Figure *f; MovementVector *v;
board.f( start, end, f, v );

(II.)

Figure *f; MovementVector *v;
std::Pair<Figure*, MovementVector*> tuple = board.f( start, end );
f = tuple.first; v = tuple.second;

In Java the only solutions I can think of are:

  1. Using a List as a substitute for Tuple. But the problem is I do not define types there and using a raw List I think is discouraged.
  2. Implement custom generic class Pair.

I would like to know what is the best practice or how can I do it in a way that feels natural for Java. I personally like (I.) best, but it's impossible here. The problem I have with other solutions is that I access the elements of a tuple in a way that doesn't suggest what they contain and I think it goes a bit against literate programming paradigm.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
infoholic_anonymous
  • 969
  • 3
  • 12
  • 34
  • 5
    I tend to either use List for single types, e.g. String, Int, etc. Or for more complex values create my own DTO class to get returned. – Max Dec 16 '14 at 21:14
  • For tuple support in Java, check out [javatuples](http://www.javatuples.org/). – Alexis King Dec 16 '14 at 21:17
  • And also http://stackoverflow.com/questions/6271731/whats-the-best-way-to-return-a-pair-of-values-in-java – Raedwald Dec 16 '14 at 21:20
  • 1
    The advantage of the DTO approach is that its properties can better express the intent than positions within a list -- I'd prefer a Map to a List, and possibly a (lightweight, inner-class?) DTO over a Map – Dexygen Dec 16 '14 at 21:22
  • Also, here is a [relevant discussion talking about introducing `Pair` into Java](https://groups.google.com/forum/#!topic/comp.lang.java.help/-LY_xkXBtIc) – mkobit Dec 16 '14 at 21:26
  • @Max and where do you put the code for the DTO? I guess it is to have package visibility. Then, a separate file or under the class which method is to return it (in my example: in `CheckersBoard.java`)? – infoholic_anonymous Dec 16 '14 at 21:41
  • @infoholic_anonymous The DTO can be a separate class (file) or it can be an inner class. It just holds the variables you want to return with basic getters and setters. If it is a separate file you will have to declare the import (your IDE will probably automatically know where it is though). Then in your return method you shove all the values into the DTO and return that. – Max Dec 16 '14 at 23:53

5 Answers5

3

You could define an inner container for the two Objects that implements Map.Entry<Figure,MovementVector>, then use getKey() to get the Figure Object and getValue() to get the MovementVector. For example:

private class MyEntryClass<K,V> implements Map.Entry<K,V> {
    private final K key;
    private V value;

    public MyEntryClass(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }

    public V setValue(V value) {
        V old = this.value;
        this.value = value;
        return old;
    }
}

Then (assuming f is your Figure and v is your MovementVector) you could just return new MyEntryClass<Figure,MovementVector>(f,v);

EDIT: made class parameters generic for the sake of extensibility/generalizability

TayTay
  • 6,882
  • 4
  • 44
  • 65
  • 1
    imho that's a very interesting solution, thanks! – infoholic_anonymous Dec 16 '14 at 21:24
  • I do like this solution far more. I'd recommend using this. – Juxhin Dec 16 '14 at 21:37
  • Why does `MyEntryClass` still need type parameters? If they're always going to be `Figure` and `MovementVector` (as you indicate by `implements Map.Entry
    `), you could simplify things by making `MyEntryClass` non-generic.
    – Edward Dec 16 '14 at 21:44
  • That's fair. I left the generic types in should he/she want to make it a generically-typed datastructure, but parameterized it based on the question specifics. It could either remain generic or lose the parameters – TayTay Dec 16 '14 at 21:46
  • Why not just use `AbstractMap.SimpleEntry`, which already does this for you? – Louis Wasserman Dec 16 '14 at 22:12
1

You are only permitted to return one thing, you may not return multiple objects unless they are stored within an array and you return the actual array instead.

It is better to simple store the objects in a List<T> and simply return that List in the method. From that you may directly retrieve any element you want within that array.

I also realised you mentions pair of objects. If you wish to store and retrieve objects in a specific structure you may create (as Max suggested) a custom DTO class and simply returning that.

Juxhin
  • 5,068
  • 8
  • 29
  • 55
  • 1
    If the two Objects to return are of different types, you run the risk of either a rawtyped List or an unchecked add operation – TayTay Dec 16 '14 at 21:32
  • @Tgsmith61591 - That is true, my answer was towards the idea of running the same type – Juxhin Dec 16 '14 at 21:35
1

Common-Lang from Apache already defines a Pair type for your convenience, if you want to use it. The tuple subpackage also defines a lot of useful containers as well.

That said, I'd say that a situation like this would call for an object to encapsulate the two of those values together; if you need to return both of them, then using a wrapper with more meaning than Pair<Figure, MovementVector> may be better for you in the long run.

Makoto
  • 104,088
  • 27
  • 192
  • 230
1

There are at least 4 basic options I can think of:

  1. Return a List<Object> or an Object[].

  2. Return a Pair or Tuple class from a non-core library. Public methods should probably not do this as the getters have meaningless names.

  3. Create your own custom type and return that. This is often the best solution.

  4. Allow one of the method parameters to be mutable. For example if you want to return 3 doubles and a String, you can make one of the method parameters double[] arr. Then the method can assign values to arr[0], arr[1] and arr[2] and return a String. This is a bit clumsy but can be useful at times.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
0

if you're returning two different types, I'd definitely not recommend using a List, for the type reason you mention yourself. My suggestion would be creating a result/response type such as

Tuple<Figure,Movement>

or reuse Map.Entry.

Also, read this question and answers.

Cheers,

Community
  • 1
  • 1
Anders R. Bystrup
  • 15,729
  • 10
  • 59
  • 55