Java: How to implement a method that takes 2 arrays and returns 2 arrays?

Ok, here's what I want to do:

I want to implement a crossover method for arrays.

It is supposed to take 2 arrays of the same size and return two new arrays, which are a variation of the two input arrays. as in [a, a, a, a] [b, b, b, b] ------> [a, a, b, b] [b, b, a, a].

Now I am wondering what the suggested way to do this in Java would be, since I cannot return more than one value.

My ideas: - Returning a collection (or array) containing both new arrays.

I don't like this because he thinks the code will be harder to understand. - avoiding the need to return two results by calling the method for each case, but getting one of the results each time.

I don't like this either, because there will be no natural order about which solution to return. You will need to specify this, but it will make the code harder to understand.

Plus, this will only work for this basic case, but I will want to shuffle the array before the crossover and vice versa after that. I cannot do the shuffle isolated from the crossover as I don't want to actually do the operation, instead I want to use the permutation information by doing the crossover, which would be a more efficient way I think.

My question is not about the algorithm itself, but the way the method is input (relative to input and output) in Java

+2


a source to share


10 replies


Following a suggestion from Bruce Eckel's book Thinking in Java, in my Java projects, I often include some utility classes to combine groups of two or three objects. They are trivial and convenient, especially for methods that must return multiple objects. For instance:



public class Pair<TA,TB> {
    public final TA a;
    public final TB b;

    /**
     * factory method
     */
    public static <TA,TB> Pair<TA,TB> createPair(TA a,TB b ){
        return new Pair<TA,TB>(a,b);
    }

    /**
     * private constructor - use instead factory method 
     */
    private Pair(final TA a, final TB b) {
            this.a = a;
            this.b = b; 
    }

    public String toString() {  
        return "(" + a + ", " + b + ")";
    }

}

      

+11


a source


Read the last section of this article:

http://www.yoda.arachsys.com/java/passing.html

Quote:



This is the real reason why reference is used in many cases - it allows many to return values ​​efficiently. Java does not allow multiple "real" return values, and it does not allow traversal semantics to be used in other single-return languages. However, here are some methods to get around this:

  • If any of your return values ​​are status codes that indicate success or failure of the method, eliminate them immediately. Replace them with exception handling, which throws an exception if the method does not complete successfully. Exception is a more standard way to handle an error condition, can be more expressive and eliminate one of your return values.

  • Find related groups of return values ​​and encapsulate them in objects containing each piece of information as fields . Classes for these objects can be extended to encapsulate their behavior later to further improve the design of the code. Each set of associated return values ​​that you encapsulate in an object removes the return values ​​from the method by raising the abstraction of the method interface. For example, instead of passing coordinates X and Y by reference allow them to return, create a mutable Point class, pass the reference object by value, and update the object's values ​​within the method.

As a bonus, this section has been updated by Jon Skeet :)

+6


a source


If it makes sense for the caller to know the size of the returned arrays ahead of time, you can pass them to the method:

     public void foo(Object[] inOne, Object[] inTwo, Object[] outOne, Object[] outTwo) {
            //etc.
     }

      

That being said, 90 +% of the time the multiple return values ​​from the method hide the best design. My solution would be to do the transformation inside the object:

     public class ArrayMixer {
           private Object[] one;
           private Object[] two;
           public ArrayMixer(Object[] first, Object[] second) {
                //Mix the arrays in the constructor and assign to one and two.
           }
           public Object[] getOne() { return one; }
           public Object[] getTwo() { return two; }
     }

      

I suspect that in your real use case, class and array one and two arrays might get better names.

+5


a source


Since the specification of your method is that it takes two input arrays and creates output arrays, I agree with you that the method should return both arrays at the same time.

I think the most natural choice for a return value is int[][]

length 2 (replace with int

whatever type you use). I see no reason why it should make the code more difficult to understand, especially if you specify what the content of the return value will be.

Edit : In response to your comment, I understand that you've considered this, and I'm saying that, despite your stylistic objections, I don't believe there is strictly a "better" alternative ("better" is clearly defined in the question here).

An alternative approach, largely equivalent to this, would be to define an object that wraps two arrays. This has a slight difference in being able to refer to them by name rather than by array indices.

+3


a source


The best way to do it is to do

public void doStuff(int[] array1, int[] array2) {
    // Put code here
}

      

Since Java arrays in Java pass a reference, any changes made to arrays will be made to the array itself. This has a few caveats.

  • If you are setting to null you have to use another way (like encapsulating it in an object)
  • If you are initializing an array (in a method) you have to use another way

You would use this in the format:

// other method
int[] array1 = new int[20];  // the arrays can be whatever size
int[] array2 = new int[20];

doStuff(array1,array2);

// do whatever you need to with the arrays

      

Edit: This makes the assumption that changes can be made to the input arrays.

If it is not, then the object (for example, in leonbloy the answer is definitely what is called).

+2


a source


You strictly cannot return more than one value (think object or primitive) in Java. Maybe you can return an instance of a specific Result object that has two arrays as properties?

0


a source


You can pass the output arrays as parameters to the method. This can give you more control over memory allocation for arrays too.

0


a source


The cleanest and easiest way to understand is to create a container bean containing two arrays and return the container from the method. I would probably also pass the container to the method so that it is symmetric.

The most memory efficient way, assuming both arrays are the same length, would be to pass a multidimensional array - Object [2] [n] - where n is the length of the arrays.

0


a source


If you really are against an arbitrary order that comes from a 2d array or collection, perhaps consider creating an inner class that reflects the logic of what you are doing. You can simply define a class that contains two arrays, and you could return your method, with names and functions that reflect the logic of what you are doing.

0


a source


A simple solution to this problem is to return as a Map. The trick of this question is how you define keys to identify objects, say there are two input arrays [a, a, a, a] [b, b, b, b] and two output arrays [a, a, b, b] [b, b, a, a]

To do this, you can use a String variable as a key only to identify objects, because a String variable is immutable, so they can be used as keys. And as an example

   Map<String,String[]> method(String[] x,String[] y){

do your stuff..........

   Hashmap<String,String[]> map =new HashMap<String,String[]>();
map.put("Object2",[b,b,a,a]);

return map;
}

      

0


a source







All Articles