How to return multiple objects from a Java method?

前端 未结 25 3069
眼角桃花
眼角桃花 2020-11-21 23:55

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<

相关标签:
25条回答
  • 2020-11-22 00:43

    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.

    0 讨论(0)
  • 2020-11-22 00:46

    Regarding the issue about multiple return values in general I usually use a small helper class that wraps a single return value and is passed as parameter to the method:

    public class ReturnParameter<T> {
        private T value;
    
        public ReturnParameter() { this.value = null; }
        public ReturnParameter(T initialValue) { this.value = initialValue; }
    
        public void set(T value) { this.value = value; }
        public T get() { return this.value; }
    }
    

    (for primitive datatypes I use minor variations to directly store the value)

    A method that wants to return multiple values would then be declared as follows:

    public void methodThatReturnsTwoValues(ReturnParameter<ClassA> nameForFirstValueToReturn, ReturnParameter<ClassB> nameForSecondValueToReturn) {
        //...
        nameForFirstValueToReturn.set("...");
        nameForSecondValueToReturn.set("...");
        //...
    }
    

    Maybe the major drawback is that the caller has to prepare the return objects in advance in case he wants to use them (and the method should check for null pointers)

    ReturnParameter<ClassA> nameForFirstValue = new ReturnParameter<ClassA>();
    ReturnParameter<ClassB> nameForSecondValue = new ReturnParameter<ClassB>();
    methodThatReturnsTwoValues(nameForFirstValue, nameForSecondValue);
    

    Advantages (in comparison to other solutions proposed):

    • You do not have to create a special class declaration for individual methods and its return types
    • The parameters get a name and therefore are easier to differentiate when looking at the method signature
    • Type safety for each parameter
    0 讨论(0)
  • 2020-11-22 00:47

    In the event the method you're calling is private, or called from one location, try

    return new Object[]{value1, value2};
    

    The caller looks like:

    Object[] temp=myMethod(parameters);
    Type1 value1=(Type1)temp[0];  //For code clarity: temp[0] is not descriptive
    Type2 value2=(Type2)temp[1];
    

    The Pair example by David Hanak has no syntactic benefit, and is limited to two values.

    return new Pair<Type1,Type2>(value1, value2);
    

    And the caller looks like:

    Pair<Type1, Type2> temp=myMethod(parameters);
    Type1 value1=temp.a;  //For code clarity: temp.a is not descriptive
    Type2 value2=temp.b;
    
    0 讨论(0)
  • 2020-11-22 00:47

    You can utilize a HashMap<String, Object> as follows

    public HashMap<String, Object> yourMethod()
    {
    
       .... different logic here 
    
      HashMap<String, Object> returnHashMap = new HashMap<String, Object>();
      returnHashMap.put("objectA", objectAValue);
      returnHashMap.put("myString", myStringValue);
      returnHashMap.put("myBoolean", myBooleanValue);
    
      return returnHashMap;
    }
    

    Then when calling the method in a different scope, you can cast each object back to its initial type:

    // call the method
    HashMap<String, Object> resultMap = yourMethod();
                    
    // fetch the results and cast them
    ObjectA objectA = (ObjectA) resultMap.get("objectA");
    String myString = (String) resultMap.get("myString");
    Boolean myBoolean = (Boolean) resultMap.get("myBoolean");
    
    0 讨论(0)
  • 2020-11-22 00:47

    I have a been using a very basic approach to deal with problems of multiple returns. It serves the purpose, and avoids complexity.

    I call it the string separator Approach

    And it is effective as it can even return values of Multiple Types e.g. int,double,char,string etc

    In this approach we make a use of a string that is very unlikely to occur generally. We call it as a separator. This separator would be used to separate various values when used in a function

    For example we will have our final return as (for example) intValue separator doubleValue separator... And Then using this string we will retrieve all the information required, that can be of diffrent types as well

    Following code will Show the working of this concept

    The separator used is !@# and 3 values are being returned intVal,doubleVal and stringVal

            public class TestMultipleReturns {
    
                public static String multipleVals() {
    
                    String result = "";
                    String separator = "!@#";
    
    
                    int intVal = 5;
                    // Code to process intVal
    
                    double doubleVal = 3.14;
                    // Code to process doubleVal
    
                    String stringVal = "hello";
                    // Code to process Int intVal
    
                    result = intVal + separator + doubleVal + separator + stringVal + separator;
                    return (result);
                }
    
                public static void main(String[] args) {
    
                    String res = multipleVals();
    
                    int intVal = Integer.parseInt(res.split("!@#")[0]);
                    // Code to process intVal
    
                    double doubleVal = Double.parseDouble(res.split("!@#")[1]);
                    // Code to process doubleVal
    
                    String stringVal = res.split("!@#")[2];
    
                    System.out.println(intVal+"\n"+doubleVal+"\n"+stringVal);
                }
            }
    

    OUTPUT

    5
    3.14
    hello
    BUILD SUCCESSFUL (total time: 2 seconds)
    
    0 讨论(0)
  • 2020-11-22 00:48

    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.

    0 讨论(0)
提交回复
热议问题