3

I have written a method in Java which returns 2 values. 1st Count of result which is of int type and 2nd if the method is success true/false boolean type. How can I return both values? So that if the method is a success then only proceed.

Sample code:

public static void main(String args[])
{
    int count = 0;
    boolean status = false;
    //count = retrieveData(); Current code working but captures only 1 values at a time i.e. Count not the status

    /* Expected Code

    if (status == true)  // where status and count is returned from retrieveData method
    {
        count = retrieveData();
        System.out.println("Status is true so can proceed");
    }

    else
        System.out.println("Status is not true so don't proceed");
    */
}





public static int retrieveData() throws  Exception 
    {

        boolean success = false;
        String query = "SELECT Count(1) FROM Account";
        int totalCount=0;
        ResultSet rsRetrieve = null;
            Statement stmt = null;
            stmt = conn.createStatement();
            rsRetrieve = stmt.executeQuery(query);
            while (rsRetrieve.next())
            {
                totalCount= rsRetrieve.getInt(1);
                System.out.println("totalCount : "+totalCount);
            }


        success = true;
        return totalCount; // current working code but returns only 1 value i.e. Count not status

        /*   Expected

        return success + totalCount

        */
    }
Vikas J
  • 795
  • 3
  • 14
  • 31
  • There is the option to return a `Map.Entry`, you could use an `Integer` as key and the `Boolean` as value... – deHaar Apr 30 '19 at 10:45
  • You could return an array, a map or even better a custom class to hold all the values that you need to return. Unfortunately few coding languages can do what Golang does. – Lucat Apr 30 '19 at 10:48
  • Since the count of the result is supposed to be zero or more, you can just return a negative number when you want to indicate that the operation failed. – RealSkeptic Apr 30 '19 at 10:48
  • 1
    Also, how is it possible for it not to succeed? If you get an exception, you are throwing it (avoid `throws Exception` - be specific). Is there a way of "not succeeding" which doesn't throw an exception? – RealSkeptic Apr 30 '19 at 10:51
  • I have voted to reopen this question on the grounds that returning more than one value is not even necessary (or best practice) here. – Tim Biegeleisen Apr 30 '19 at 11:12
  • In your particular case, I would recommend throwing an exception instead of returning a status value. But in general, if you want to do something like this, your options are: (1) use [`OptionalInt`](https://docs.oracle.com/javase/8/docs/api/java/util/OptionalInt.html), where a failure condition results in an absent value; (2) use `Integer`, with a `null` value indicating failure (prefer OptionalInt as it's safer); (3) use a special non-valid value, such as -1 when the only valid values are positive; (4) use some kind of pair structure, such as `Map.Entry`. – DodgyCodeException Apr 30 '19 at 13:13

6 Answers6

3

There are different ways to retun the Multiple values from a method some of the best approaches that i use are:

1- Make Class for the datatypes that you want to return for example you want to return two Strings make class like this:

public class myType {
            String a;
            String b;

            public String getA() {
                return a;
            }

            public void setA(String _a) {
                a = _a;
            }
            //And All other geter setters
        }

and make return type of your method to the above class.

2- Return Map with key value pairs
3- Make Interface and call Abstract method from where you want to return the values (You have to implement the interface in the class where you want to receive the values) Hope This will give you rough idea to move forword

2

You can create a custom java object as follows

public class Result {

   private boolean success;
   private int totalResults;

   public Result(boolean success, int totalResults){
    this.success = success;
    this.totalResults = totalResults;
   }
   public boolean getSuccess(){
     return this.success;
   }

   public boolean getTotalResults(){
       return this.totalResults;
   }

}
Vikram Patil
  • 628
  • 6
  • 20
1

I'd like to use any[1] to simulate pointers as out. Like C++ *p and C# out.

boolean[] p_status = new boolean[1];
int count = retrieveData(p_status);
boolean status = p_status[0];

other sample, eneric:

public static void main(String[] args) throws JsonProcessingException {
    // I try to analysis the string, but don't want to create a new class
    var strs = "1,2,ABC,3,4,6,7,1,6,9,XYZ,3,6,3,7,9,2,5,9,ABC";

    // use any[1] as pointer
    int[] p_iStrCount = new int[1];
    // when facing eneric, it's a little different
    @SuppressWarnings("unchecked") HashMap<Integer, Integer>[] p_hmNum = new HashMap[1];

    // use pointer as parameters, so I can get multiple results out
    var hmStr = analysis(strs, p_iStrCount, p_hmNum);
    var iStrCount = p_iStrCount[0];
    var hmNum = p_hmNum[0];
}

// `strs` as input
// `pOut_iStrCount`, `pOut_hmNum`, `return` as output
// You can ignore the details of this method
static HashMap<String, Integer> analysis(@NotNull String strs, @Nullable int[] pOut_iStrCount, @Nullable HashMap<Integer, Integer>[] pOut_hmNum){

    var aryStr = StringUtils.split(strs, ",");
    var iStrCount = null != aryStr ? aryStr.length : 0;
    var hmStr = new HashMap<String, Integer>();
    var hmNum = new HashMap<Integer, Integer>();

    if(null != aryStr){
        for(String str : aryStr){
            hmStr.compute(str, (k,v)->(null == v ? 0 : v + 1));
            int num;
            try{
                num = Integer.parseInt(str);
            }catch (NumberFormatException ignore){
                continue;
            }
            hmNum.compute(num, (k,v)->(null == v ? 0 : v + 1));
        }
    }

    if(null != pOut_iStrCount){ pOut_iStrCount[1] = iStrCount; }
    if(null != pOut_hmNum){ pOut_hmNum[1] = hmNum; }

    return hmStr;
}
Keillion
  • 19
  • 4
0

I recommend sticking with your current general approach and not trying to return two pieces of information from your method. Your method signature throws an exception, and one possible way to handle this would be to have your method throw an exception when something goes wrong. Otherwise, it means that the count query did run, and some count would be returned. But, you should probably have a try catch block surrounding your JDBC code:

public static int retrieveData(Connection conn) throws Exception {
    Statement stmt = null;
    int totalCount = 0;

    try {
        String query = "SELECT COUNT(*) FROM Account";

        ResultSet rsRetrieve;
        stmt = conn.createStatement();
        rsRetrieve = stmt.executeQuery(query);

        if (rsRetrieve.next()) {
            totalCount = rsRetrieve.getInt(1);
            System.out.println("totalCount : " + totalCount);
        }
    }
    catch (SQLException e) {
        System.out.println(e.getMessage());
        threw new Exception("something went wrong");
    }
    finally {
        if (stmt != null) {
            stmt.close();
        }

        if (conn != null) {
            conn.close();
        }

    }

    return totalCount;
}

So the pattern being used here is that if something goes wrong, there is no count, and the caller gets an exception. Otherwise, if no exception happens, then some count would be returned.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • I think the only way this code may fail is when an SQL Exception occurs (or some unexpected runtime error). If you caught it and didn't throw it again, you are missing a return statement. Also, what is `conn()`? – RealSkeptic Apr 30 '19 at 10:53
  • @RealSkeptic Thanks for being such a skeptic. I fixed those typos. Yes, there could be some other exception, but we don't typically expect unchecked exceptions anyway (at least this is my reasoning). – Tim Biegeleisen Apr 30 '19 at 10:54
  • 1
    Part of my point was, though, that there is no point in catching the exception anyway - and certainly not in replacing it with a generic `Exception`. Just let it be thrown. Of course, replacing with a custom exception may be useful sometimes, but I would not encourage a beginner to just throw `Exception`. – RealSkeptic Apr 30 '19 at 10:59
  • My point is that we _should_ catch the exception, since we need a `finally` block in any case, and beyond that maybe we would like to do some custom logging. – Tim Biegeleisen Apr 30 '19 at 10:59
  • 1
    Why does a `finally` block imply that you need to catch the exception? Custom logging is a fine thing, but each application has its own logging demands and if there is going to be a catch clause for this in the caller - which is the point of the question, to distinguish between success and failure - it may be better to log there. In any case, why not rethrow the original exception and replace it with one that doesn't contain any information about what happened? – RealSkeptic Apr 30 '19 at 11:04
0

You can’t but you can create a bean class for holding multiple objects.

If this is for programmatic error handling you may want to have a look at Optional (standard) or Either (vavr) to handle multiple outcomes

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
-1

You can use Java Pair

import javafx.util.Pair;

public Pair retrieveData(int a, int b) {
   return new Pair(a, b);
}

Pair p = retrieveData(1,2);
int a = p.getKey();     // 1
int b = p.getValue();   // 2
hqt
  • 29,632
  • 51
  • 171
  • 250